<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>C++内存管理 | whoway</title>
    <meta name="description" content="Personal Blog Website">
    <link rel="icon" href="/images/photo.jpg">
  <link rel="manifest" href="/images/photo.jpg">
  <link rel="apple-touch-icon" href="/images/photo.jpg">
  <meta http-quiv="pragma" cotent="no-cache">
  <meta http-quiv="pragma" cotent="no-cache,must-revalidate">
  <meta http-quiv="expires" cotent="0">
    
    <link rel="preload" href="/assets/css/0.styles.0dbae9ec.css" as="style"><link rel="preload" href="/assets/js/app.c70e21ad.js" as="script"><link rel="preload" href="/assets/js/31.831b195d.js" as="script"><link rel="prefetch" href="/assets/js/10.15222a53.js"><link rel="prefetch" href="/assets/js/100.7e0e5a86.js"><link rel="prefetch" href="/assets/js/101.efd59f25.js"><link rel="prefetch" href="/assets/js/102.dfbdc06c.js"><link rel="prefetch" href="/assets/js/103.d3ab2109.js"><link rel="prefetch" href="/assets/js/104.117957ef.js"><link rel="prefetch" href="/assets/js/105.046e8ff3.js"><link rel="prefetch" href="/assets/js/106.aebdc17d.js"><link rel="prefetch" href="/assets/js/107.248733c2.js"><link rel="prefetch" href="/assets/js/108.a2fecadc.js"><link rel="prefetch" href="/assets/js/109.35196857.js"><link rel="prefetch" href="/assets/js/11.770642f2.js"><link rel="prefetch" href="/assets/js/110.cf3d973c.js"><link rel="prefetch" href="/assets/js/111.f985889a.js"><link rel="prefetch" href="/assets/js/112.ad614f41.js"><link rel="prefetch" href="/assets/js/113.f666653c.js"><link rel="prefetch" href="/assets/js/114.c6c3f384.js"><link rel="prefetch" href="/assets/js/115.e51d3c2f.js"><link rel="prefetch" href="/assets/js/116.4f4b39f5.js"><link rel="prefetch" href="/assets/js/117.99352e11.js"><link rel="prefetch" href="/assets/js/118.c6ae6572.js"><link rel="prefetch" href="/assets/js/119.4ccbe778.js"><link rel="prefetch" href="/assets/js/12.042a92ff.js"><link rel="prefetch" href="/assets/js/120.edda1c4f.js"><link rel="prefetch" href="/assets/js/121.30a638ed.js"><link rel="prefetch" href="/assets/js/122.6efcefb1.js"><link rel="prefetch" href="/assets/js/123.91e6665b.js"><link rel="prefetch" href="/assets/js/124.f27e3d7e.js"><link rel="prefetch" href="/assets/js/125.c75712d5.js"><link rel="prefetch" href="/assets/js/126.ed756cce.js"><link rel="prefetch" href="/assets/js/127.2f06c74c.js"><link rel="prefetch" href="/assets/js/128.d5f6f30e.js"><link rel="prefetch" href="/assets/js/129.508b7eed.js"><link rel="prefetch" href="/assets/js/13.b5280c37.js"><link rel="prefetch" href="/assets/js/130.dc05f9aa.js"><link rel="prefetch" href="/assets/js/131.e0ba69b1.js"><link rel="prefetch" href="/assets/js/132.d79bcaa4.js"><link rel="prefetch" href="/assets/js/133.34acc01a.js"><link rel="prefetch" href="/assets/js/134.dabf64d5.js"><link rel="prefetch" href="/assets/js/135.ad90c915.js"><link rel="prefetch" href="/assets/js/136.dbb0074f.js"><link rel="prefetch" href="/assets/js/137.284ad365.js"><link rel="prefetch" href="/assets/js/138.a4b6856f.js"><link rel="prefetch" href="/assets/js/139.c9c1e20f.js"><link rel="prefetch" href="/assets/js/14.df02ba38.js"><link rel="prefetch" href="/assets/js/140.8b0a9269.js"><link rel="prefetch" href="/assets/js/141.9c7759c5.js"><link rel="prefetch" href="/assets/js/142.a4201a82.js"><link rel="prefetch" href="/assets/js/143.d7da6e8c.js"><link rel="prefetch" href="/assets/js/144.5e48e65d.js"><link rel="prefetch" href="/assets/js/145.a0e2633c.js"><link rel="prefetch" href="/assets/js/146.3c775f9b.js"><link rel="prefetch" href="/assets/js/147.22add89a.js"><link rel="prefetch" href="/assets/js/148.cfde1009.js"><link rel="prefetch" href="/assets/js/149.ffc835b5.js"><link rel="prefetch" href="/assets/js/15.fbdfc4ee.js"><link rel="prefetch" href="/assets/js/150.406c4b20.js"><link rel="prefetch" href="/assets/js/151.b2040eea.js"><link rel="prefetch" href="/assets/js/152.7bc65661.js"><link rel="prefetch" href="/assets/js/153.1d7c65e3.js"><link rel="prefetch" href="/assets/js/154.1309de49.js"><link rel="prefetch" href="/assets/js/155.81d3ee1f.js"><link rel="prefetch" href="/assets/js/156.154a4ef2.js"><link rel="prefetch" href="/assets/js/16.e5eb6147.js"><link rel="prefetch" href="/assets/js/17.57853c4a.js"><link rel="prefetch" href="/assets/js/18.cb9d7518.js"><link rel="prefetch" href="/assets/js/19.f354dc47.js"><link rel="prefetch" href="/assets/js/2.570d8a23.js"><link rel="prefetch" href="/assets/js/20.b5af7fad.js"><link rel="prefetch" href="/assets/js/21.0b1928fe.js"><link rel="prefetch" href="/assets/js/22.f78666de.js"><link rel="prefetch" href="/assets/js/23.29c3f366.js"><link rel="prefetch" href="/assets/js/24.6f596516.js"><link rel="prefetch" href="/assets/js/25.14067b60.js"><link rel="prefetch" href="/assets/js/26.74ba4989.js"><link rel="prefetch" href="/assets/js/27.13d60edd.js"><link rel="prefetch" href="/assets/js/28.9523cb32.js"><link rel="prefetch" href="/assets/js/29.8ec842e9.js"><link rel="prefetch" href="/assets/js/3.3fb3d2e0.js"><link rel="prefetch" href="/assets/js/30.805597a8.js"><link rel="prefetch" href="/assets/js/32.063c672d.js"><link rel="prefetch" href="/assets/js/33.6d93fac3.js"><link rel="prefetch" href="/assets/js/34.56e8263c.js"><link rel="prefetch" href="/assets/js/35.dbe688bb.js"><link rel="prefetch" href="/assets/js/36.dc5af2c1.js"><link rel="prefetch" href="/assets/js/37.0a7494f6.js"><link rel="prefetch" href="/assets/js/38.fe4fc171.js"><link rel="prefetch" href="/assets/js/39.f5ed5e92.js"><link rel="prefetch" href="/assets/js/4.2c405ec8.js"><link rel="prefetch" href="/assets/js/40.fe7e2714.js"><link rel="prefetch" href="/assets/js/41.30b0811d.js"><link rel="prefetch" href="/assets/js/42.76f52d62.js"><link rel="prefetch" href="/assets/js/43.e7bb0817.js"><link rel="prefetch" href="/assets/js/44.ead0e883.js"><link rel="prefetch" href="/assets/js/45.235df046.js"><link rel="prefetch" href="/assets/js/46.5f09e829.js"><link rel="prefetch" href="/assets/js/47.67116354.js"><link rel="prefetch" href="/assets/js/48.31f34543.js"><link rel="prefetch" href="/assets/js/49.10b5ebba.js"><link rel="prefetch" href="/assets/js/5.6f47322c.js"><link rel="prefetch" href="/assets/js/50.c0f0b7f1.js"><link rel="prefetch" href="/assets/js/51.5143f3bf.js"><link rel="prefetch" href="/assets/js/52.eeddfd48.js"><link rel="prefetch" href="/assets/js/53.eb790db5.js"><link rel="prefetch" href="/assets/js/54.8fe5421c.js"><link rel="prefetch" href="/assets/js/55.d8f9004b.js"><link rel="prefetch" href="/assets/js/56.62ac9b92.js"><link rel="prefetch" href="/assets/js/57.a9caec0d.js"><link rel="prefetch" href="/assets/js/58.f93fc522.js"><link rel="prefetch" href="/assets/js/59.a81a03aa.js"><link rel="prefetch" href="/assets/js/6.8c2ea393.js"><link rel="prefetch" href="/assets/js/60.ab782775.js"><link rel="prefetch" href="/assets/js/61.6dd12daf.js"><link rel="prefetch" href="/assets/js/62.76f4b01f.js"><link rel="prefetch" href="/assets/js/63.6f8a4742.js"><link rel="prefetch" href="/assets/js/64.6f8bb1fa.js"><link rel="prefetch" href="/assets/js/65.4120a44b.js"><link rel="prefetch" href="/assets/js/66.360c2d2b.js"><link rel="prefetch" href="/assets/js/67.26f84d32.js"><link rel="prefetch" href="/assets/js/68.68f45e5e.js"><link rel="prefetch" href="/assets/js/69.e311eb56.js"><link rel="prefetch" href="/assets/js/7.6762b2d7.js"><link rel="prefetch" href="/assets/js/70.cea82674.js"><link rel="prefetch" href="/assets/js/71.783ddcf7.js"><link rel="prefetch" href="/assets/js/72.e5467385.js"><link rel="prefetch" href="/assets/js/73.b8fb681b.js"><link rel="prefetch" href="/assets/js/74.1bae37db.js"><link rel="prefetch" href="/assets/js/75.024387e5.js"><link rel="prefetch" href="/assets/js/76.a8e53010.js"><link rel="prefetch" href="/assets/js/77.8c55500a.js"><link rel="prefetch" href="/assets/js/78.7ce90bf5.js"><link rel="prefetch" href="/assets/js/79.ef71713f.js"><link rel="prefetch" href="/assets/js/8.788a6364.js"><link rel="prefetch" href="/assets/js/80.acad589d.js"><link rel="prefetch" href="/assets/js/81.02670d10.js"><link rel="prefetch" href="/assets/js/82.53b7b1ac.js"><link rel="prefetch" href="/assets/js/83.99eb8581.js"><link rel="prefetch" href="/assets/js/84.d1535ce3.js"><link rel="prefetch" href="/assets/js/85.fe2b7de9.js"><link rel="prefetch" href="/assets/js/86.41850272.js"><link rel="prefetch" href="/assets/js/87.1cdc6df9.js"><link rel="prefetch" href="/assets/js/88.01bf3461.js"><link rel="prefetch" href="/assets/js/89.17c69819.js"><link rel="prefetch" href="/assets/js/9.3813842d.js"><link rel="prefetch" href="/assets/js/90.f6ae7e35.js"><link rel="prefetch" href="/assets/js/91.507bc284.js"><link rel="prefetch" href="/assets/js/92.90551782.js"><link rel="prefetch" href="/assets/js/93.dc442d78.js"><link rel="prefetch" href="/assets/js/94.315f4e94.js"><link rel="prefetch" href="/assets/js/95.ccd6c6bf.js"><link rel="prefetch" href="/assets/js/96.0c6d89d0.js"><link rel="prefetch" href="/assets/js/97.1a9f10a9.js"><link rel="prefetch" href="/assets/js/98.43be3caa.js"><link rel="prefetch" href="/assets/js/99.54c8207b.js">
    <link rel="stylesheet" href="/assets/css/0.styles.0dbae9ec.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">whoway</span></a> <div class="links" style="max-width:nullpx;"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🎓Coding</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/00.Coding/TheBeautyOfProgramming/" class="nav-link">🔖编程之美题解</a></li><li class="dropdown-item"><!----> <a href="/00.Coding/CodeWarehouse/" class="nav-link">🔖代码意识流</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🚀语言</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/01.Language/Overview/" class="nav-link">🔖概述</a></li><li class="dropdown-item"><!----> <a href="/01.Language/C/" class="nav-link">⭐️C</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Cpp/" class="nav-link router-link-active">🚀C++</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Java/" class="nav-link">☕️Java</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Python/" class="nav-link">🧩Python3</a></li></ul></div></div><div class="nav-item"><a href="/02.Hardware/" class="nav-link">✔️硬件基础</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⭐️软件基础</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/03.Software/01.DataStructureAndAlgorithm/" class="nav-link">🐾数据结构和算法</a></li><li class="dropdown-item"><!----> <a href="/03.Software/02.OS/" class="nav-link">💻操作系统</a></li><li class="dropdown-item"><!----> <a href="/03.Software/03.Net/" class="nav-link">☁️计算机网络</a></li><li class="dropdown-item"><!----> <a href="/03.Software/04.SE/" class="nav-link">✅软件工程</a></li></ul></div></div><div class="nav-item"><a href="/04.Database/" class="nav-link">🎨数据库</a></div><div class="nav-item"><a href="/05.Engineer/" class="nav-link">🔖学术/工程</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⚙️工具</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/06.Tools/01.employment/" class="nav-link">🔖求职</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/02.efficiency/" class="nav-link">🚀效能</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/03.windows/" class="nav-link">⚙️Windows</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/04.design/" class="nav-link">🧩设计</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/05.linux/" class="nav-link">🐉Linux</a></li></ul></div></div><div class="nav-item"><a href="https://github.com/whoway" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar"><nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🎓Coding</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/00.Coding/TheBeautyOfProgramming/" class="nav-link">🔖编程之美题解</a></li><li class="dropdown-item"><!----> <a href="/00.Coding/CodeWarehouse/" class="nav-link">🔖代码意识流</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🚀语言</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/01.Language/Overview/" class="nav-link">🔖概述</a></li><li class="dropdown-item"><!----> <a href="/01.Language/C/" class="nav-link">⭐️C</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Cpp/" class="nav-link router-link-active">🚀C++</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Java/" class="nav-link">☕️Java</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Python/" class="nav-link">🧩Python3</a></li></ul></div></div><div class="nav-item"><a href="/02.Hardware/" class="nav-link">✔️硬件基础</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⭐️软件基础</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/03.Software/01.DataStructureAndAlgorithm/" class="nav-link">🐾数据结构和算法</a></li><li class="dropdown-item"><!----> <a href="/03.Software/02.OS/" class="nav-link">💻操作系统</a></li><li class="dropdown-item"><!----> <a href="/03.Software/03.Net/" class="nav-link">☁️计算机网络</a></li><li class="dropdown-item"><!----> <a href="/03.Software/04.SE/" class="nav-link">✅软件工程</a></li></ul></div></div><div class="nav-item"><a href="/04.Database/" class="nav-link">🎨数据库</a></div><div class="nav-item"><a href="/05.Engineer/" class="nav-link">🔖学术/工程</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⚙️工具</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/06.Tools/01.employment/" class="nav-link">🔖求职</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/02.efficiency/" class="nav-link">🚀效能</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/03.windows/" class="nav-link">⚙️Windows</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/04.design/" class="nav-link">🧩设计</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/05.linux/" class="nav-link">🐉Linux</a></li></ul></div></div><div class="nav-item"><a href="https://github.com/whoway" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav>  <ul class="sidebar-links"><li><div class="sidebar-group first"><p class="sidebar-heading open"><span>C++内存管理</span> <!----></p> <ul class="sidebar-group-items"><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#📑目录" class="sidebar-link">📑目录</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_00-简介" class="sidebar-link">00.简介</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#🐋重要概念传送门" class="sidebar-link">🐋重要概念传送门</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#✅第1讲-primitives⭐️" class="sidebar-link">✅第1讲-Primitives⭐️</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_01-overview" class="sidebar-link">01.Overview</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_1-1-讲解目录" class="sidebar-link">1.1.讲解目录</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#ppt-你应该具备的基础" class="sidebar-link">PPT.你应该具备的基础</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#ppt-我们的目标" class="sidebar-link">PPT.我们的目标</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_1-4-参考站点" class="sidebar-link">1.4.参考站点</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#ppt-你将获得的代码" class="sidebar-link">PPT.你将获得的代码</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_02-内存分配的每一层面『图好』✅" class="sidebar-link">02.内存分配的每一层面『图好』✅</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#ppt-c-memory-primitives" class="sidebar-link">PPT.C++ memory primitives</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_03-四个层面的基本用法" class="sidebar-link">03.四个层面的基本用法</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_3-1-『内存池』✅" class="sidebar-link">3.1.『内存池』✅</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_04-基本构件之一new-delete-expression-上" class="sidebar-link">04.基本构件之一new/delete expression(上)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#重点『区别new-expression』✅" class="sidebar-link">重点『区别new expression』✅</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_05-基本构件之一new-delete-expression-中" class="sidebar-link">05.基本构件之一new/delete expression(中)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#ppt-new-delete-expression被编译器转为『3个操作』✅" class="sidebar-link">PPT.new/delete expression被编译器转为『3个操作』✅</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_06-基本构件之一new-delete-expression-下" class="sidebar-link">06.基本构件之一new/delete expression(下)</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_07-array-new和array-delete『另一种new-expression』" class="sidebar-link">07.Array new和Array delete『另一种new expression』</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_7-1-『带-不带指针的class引入的坑』✅" class="sidebar-link">7.1.『带/不带指针的class引入的坑』✅</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_7-2-记得『new-expression还包括：array-new』✅" class="sidebar-link">7.2.记得『new expression还包括：array new』✅</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_7-3-『上下cookie设计』✅" class="sidebar-link">7.3.『上下cookie设计』✅</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_7-4-关于61h本来是60h，为什么是61h" class="sidebar-link">7.4.关于61h本来是60h，为什么是61h</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_08-replacement-new" class="sidebar-link">08.Replacement new</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_8-1-我对分类的思考✅" class="sidebar-link">8.1.我对分类的思考✅</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_8-2-『术语争议』" class="sidebar-link">8.2.『术语争议』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_09-重载" class="sidebar-link">09.重载</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_9-1-侯捷再次声明『new-expression的概念』✅" class="sidebar-link">9.1.侯捷再次声明『new expression的概念』✅</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_9-2-『重载重点』" class="sidebar-link">9.2.『重载重点』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_9-3-各种new的关系" class="sidebar-link">9.3.各种new的关系</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳10-重载示例（上）" class="sidebar-link">⏳10.重载示例（上）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳11-重载示例（下）" class="sidebar-link">⏳11.重载示例（下）</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_11-1-重载placement-new-✅" class="sidebar-link">11.1.重载placement new ✅</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#🐋神奇的开始" class="sidebar-link">🐋神奇的开始</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_12-per-classallocator" class="sidebar-link">12.Per-class allocator</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『针对一个class』" class="sidebar-link">『针对一个class』</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『注意这个设计』" class="sidebar-link">『注意这个设计』</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『给class设计小型的』" class="sidebar-link">『给class设计小型的』</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『我觉得这是设计核心』" class="sidebar-link">『我觉得这是设计核心』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳13-per-class-allocator-2" class="sidebar-link">⏳13.Per-class allocator 2</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『常见的设计手法』" class="sidebar-link">『常见的设计手法』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『常量是block-size』" class="sidebar-link">『常量是Block_size』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『继承导致的坑』" class="sidebar-link">『继承导致的坑』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『注意事项』" class="sidebar-link">『注意事项』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳14-static-allocator" class="sidebar-link">⏳14.Static allocator</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『标准库设计』" class="sidebar-link">『标准库设计』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『设计手法不错』" class="sidebar-link">『设计手法不错』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『这个我们叫版本3吧，就不叫per-class版本了』" class="sidebar-link">『这个我们叫版本3吧，就不叫per-class版本了』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳15-macro-for-static-allocator" class="sidebar-link">⏳15.Macro for static allocator</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『宏用来偷懒』" class="sidebar-link">『宏用来偷懒』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『标准库的自由链表针对所有的class来服务』" class="sidebar-link">『标准库的自由链表针对所有的class来服务』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳16-new-handler" class="sidebar-link">⏳16.New Handler</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#✅第2讲std-allocator⭐️" class="sidebar-link">✅第2讲std::allocator⭐️</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳17-vc6-malloc" class="sidebar-link">⏳17.VC6 malloc()</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳18-vc6标准分配器之实现" class="sidebar-link">⏳18.VC6标准分配器之实现</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳19-bc5标准分配器之实现" class="sidebar-link">⏳19.BC5标准分配器之实现</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳20-g2-9标准分配器之实现" class="sidebar-link">⏳20.G2.9标准分配器之实现</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『你以为仅仅这样？』" class="sidebar-link">『你以为仅仅这样？』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『2333奇葩』" class="sidebar-link">『2333奇葩』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『事实上是这样』" class="sidebar-link">『事实上是这样』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳21-g2-9std-allocvs-g4-9-pull-alloc" class="sidebar-link">⏳21.G2.9std_alloc VS G4.9__pull_alloc</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳22-g4-9pull-alloc用例" class="sidebar-link">⏳22.G4.9pull_alloc用例</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳23-g2-9std-alloc" class="sidebar-link">⏳23.G2.9std alloc</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳24-g2-9std-alloc运行一瞥01-05" class="sidebar-link">⏳24.G2.9std_alloc运行一瞥01-05</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳25-g2-9std-alloc运行一瞥06-10" class="sidebar-link">⏳25.G2.9std_alloc运行一瞥06-10</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳26-g2-9std-alloc运行一瞥11-13" class="sidebar-link">⏳26.G2.9std_alloc运行一瞥11-13</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳27-g2-9std-alloc源码剖析（上）" class="sidebar-link">⏳27.G2.9std_alloc源码剖析（上）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳28-g2-9std-alloc源码剖析（中）" class="sidebar-link">⏳28.G2.9std_alloc源码剖析（中）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳29-g2-9std-alloc源码剖析（下）" class="sidebar-link">⏳29.G2.9std_alloc源码剖析（下）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳30-g2-9std-alloc观念大整理" class="sidebar-link">⏳30.G2.9std_alloc观念大整理</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳31-g4-9pull-allocator运行观察" class="sidebar-link">⏳31.G4.9pull allocator运行观察</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#✅第3讲-malloc和free底层⭐️" class="sidebar-link">✅第3讲-malloc和free底层⭐️</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳32-vc6和vc10的malloc比较" class="sidebar-link">⏳32.VC6和VC10的malloc比较</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_32-1-『补充资料』" class="sidebar-link">32.1.『补充资料』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_32-2-malloc本身不是系统调用是函数（招聘面试问）" class="sidebar-link">32.2.malloc本身不是系统调用是函数（招聘面试问）</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_32-3-《stl源码剖析》摘录" class="sidebar-link">32.3.《STL源码剖析》摘录</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『联想』" class="sidebar-link">『联想』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『新概念：sbh』" class="sidebar-link">『新概念：SBH』</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#『看到第12分钟了』" class="sidebar-link">『看到第12分钟了』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳33-vc6内存分配（1）" class="sidebar-link">⏳33.VC6内存分配（1）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳34-vc6内存分配（2）" class="sidebar-link">⏳34.VC6内存分配（2）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳35-vc6内存分配（3）" class="sidebar-link">⏳35.VC6内存分配（3）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳36-vc6内存分配（4）" class="sidebar-link">⏳36.VC6内存分配（4）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳37-vc6内存分配（5）" class="sidebar-link">⏳37.VC6内存分配（5）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳38-sbh行为分析-分配-释放之连续动作图解（1）" class="sidebar-link">⏳38.SBH行为分析-分配+释放之连续动作图解（1）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳39-sbh行为分析-分配-释放之连续动作图解（2）" class="sidebar-link">⏳39.SBH行为分析-分配+释放之连续动作图解（2）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳40-sbh行为分析-分配-释放之连续动作图解（3）" class="sidebar-link">⏳40.SBH行为分析-分配+释放之连续动作图解（3）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳41-sbh行为分析-分配-释放之连续动作图解（4）" class="sidebar-link">⏳41.SBH行为分析-分配+释放之连续动作图解（4）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳42-vc6内存管理free-p-（上）" class="sidebar-link">⏳42.VC6内存管理free(p)（上）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳43-vc6内存管理总结（上）" class="sidebar-link">⏳43.VC6内存管理总结（上）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#⏳44-vc6内存管理总结（下）" class="sidebar-link">⏳44.VC6内存管理总结（下）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#✅第4讲-loki-allocator" class="sidebar-link">✅第4讲-loki::allocator</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_45-上中下三个classes分析" class="sidebar-link">45.上中下三个classes分析</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_46-loki-allocator行为图解" class="sidebar-link">46.Loki_allocator行为图解</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_47-class-fixedallocator分析（上）" class="sidebar-link">47.class FixedAllocator分析（上）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_48-class-fixedallocator分析（下）" class="sidebar-link">48.class FixedAllocator分析（下）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_49-loki-allocator总结" class="sidebar-link">49.Loki_allocator总结</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#✅第5讲、其他" class="sidebar-link">✅第5讲、其他</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_50-gnu-c-对allocators的描述" class="sidebar-link">50.GNU C++对allocators的描述</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#智能型" class="sidebar-link">智能型</a></li></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_51-vs2013标准分配器-g4-9标准分配器与new-allocator以及g4-9malloc" class="sidebar-link">51.VS2013标准分配器&amp;G4.9标准分配器与new_allocator以及G4.9malloc</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_52-g4-9array-allocator" class="sidebar-link">52.G4.9array_allocator</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_53-g4-9-debug-allocator" class="sidebar-link">53.G4.9 debug_allocator</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_54-bitmap-allocator-上" class="sidebar-link">54.bitmap_allocator(上)</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#_55-bitmap-allocator（下）" class="sidebar-link">55.bitmap_allocator（下）</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT04.C%2B%2B%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></div></li></ul> </div> <div class="page"> <div class="content"><h1 id="c-内存管理"><a href="#c-内存管理" class="header-anchor">#</a> C++内存管理</h1> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>&lt;font style=&quot;background: yellow&quot;&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><ul><li>本部分，侯捷有几个讲错的点</li></ul> <h2 id="📑目录"><a href="#📑目录" class="header-anchor">#</a> 📑目录</h2> <p>[TOC]</p> <h2 id="_00-简介"><a href="#_00-简介" class="header-anchor">#</a> 00.简介</h2> <ul><li>00.C++内存管理简介-侯捷</li> <li>C++內存管理 101 – 从最基础到最繁复</li> <li>课程简介</li> <li>內存(memory, 台湾术语称为 “记忆体”) 是电脑中的 “脑” 吗？</li> <li>CPU才是脑， CPU才是计算机的三魂六魄。</li> <li>但若没有內存，一切只存在于虚无缥缈间，等同于不存在。</li> <li>內存曾经是最宝贵也最昂贵的周边资源，現代程序员无法想像DOS時代对內存的錙銖必較。</li> <li>俱往矣，且看今朝。我们(似乎)有用不完的便宜內存。但表象之下是操作系統和标准库做了大量工作。</li> <li>而如果你开发內存高耗軟件，或处于內存受限环境下 (例如嵌入式系統)，就有必要深刻了解操作系統和标准库为你所做的內存管理，甚至需要自行管理內存。</li></ul> <blockquote><p><strong>本课程分为5讲</strong>：</p></blockquote> <p><strong>⏳第一講：C++ 內存構件</strong></p> <ul><li>第1讲，并发展处1个小型的<code>针对每个class（per-class）</code>的自己的<font style="background:yellow;">1个小型分配器</font></li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>Overview <span class="token number">1</span><span class="token operator">-</span><span class="token number">10</span>
内存分配的每一层面 <span class="token number">11</span>
四个基本层面的用法 <span class="token number">12</span><span class="token operator">-</span><span class="token number">14</span>
基本构件之一 <span class="token keyword">new</span><span class="token operator">/</span><span class="token keyword">delete</span> expressions <span class="token number">15</span><span class="token operator">-</span><span class="token number">17</span>
基本构件之二 array <span class="token keyword">new</span><span class="token operator">/</span><span class="token keyword">delete</span> <span class="token number">18</span><span class="token operator">-</span><span class="token number">21</span>
基本构件之三 placement <span class="token keyword">new</span><span class="token operator">/</span><span class="token keyword">delete</span> <span class="token number">22</span>
基本构件之分配流程 <span class="token number">23</span><span class="token operator">-</span><span class="token number">24</span>
基本构件之重载 <span class="token number">25</span><span class="token operator">-</span><span class="token number">34</span>
Per<span class="token operator">-</span><span class="token keyword">class</span> <span class="token class-name">allocator</span> 第一版本 <span class="token number">35</span><span class="token operator">-</span><span class="token number">36</span>
Per<span class="token operator">-</span><span class="token keyword">class</span> <span class="token class-name">allocator</span> 第二版本 <span class="token number">37</span><span class="token operator">-</span><span class="token number">38</span>
Common <span class="token keyword">static</span> allocator （第三版本） <span class="token number">39</span><span class="token operator">-</span><span class="token number">41</span>
Macro allocator （第四版本） <span class="token number">42</span><span class="token operator">-</span><span class="token number">43</span>
GNU C<span class="token operator">++</span> allocator （第五版本） 样貌 <span class="token number">44</span>
杂项讨论 <span class="token number">45</span><span class="token operator">-</span><span class="token number">48</span>
    
    
C<span class="token operator">++</span>语言中与内存相关的所有基础构件 <span class="token punctuation">(</span>constructs<span class="token punctuation">)</span>，包括    
<span class="token number">1</span>、malloc<span class="token operator">/</span>free<span class="token punctuation">,</span> 
<span class="token number">2</span>、<span class="token keyword">new</span><span class="token operator">/</span><span class="token keyword">delete</span><span class="token punctuation">,</span> 
<span class="token number">3</span>、<span class="token keyword">operator</span> <span class="token keyword">new</span><span class="token operator">/</span><span class="token keyword">operator</span> <span class="token keyword">delete</span><span class="token punctuation">,</span> 
<span class="token number">4</span>、placement <span class="token keyword">new</span><span class="token operator">/</span>placement <span class="token keyword">delete</span>，
    
我將探討它們的意义、运用方式和重載方式。
并以此开发一个极小型内存池<span class="token punctuation">(</span>memory pool<span class="token punctuation">)</span>。    
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p><strong>⏳第二講：std::allocator</strong></p> <ul><li>第2讲为标准库这个<font style="background:yellow;">大型分配器</font>的做法</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>内存块布局 <span class="token number">52</span>
VC6 allocator <span class="token number">53</span>
BC5 allocator <span class="token number">54</span>
GNU allocator <span class="token number">55</span><span class="token operator">-</span><span class="token number">60</span>
GNU allocator 行为剖析 <span class="token number">61</span><span class="token operator">-</span><span class="token number">76</span>
GNU allocator 源码剖析 <span class="token number">77</span><span class="token operator">-</span><span class="token number">87</span>
GNU allocator 检讨 <span class="token number">88</span><span class="token operator">-</span><span class="token number">89</span>
GNU allocator 监视 <span class="token number">90</span><span class="token operator">-</span><span class="token number">91</span>
GNU allocator 移植到 C 语言 <span class="token number">92</span>
    
标准库的兴起，意味我们可以摆脱内存管理的繁复琐屑，直接使用容器。
    
但是容器背后的分配器（allocator）攸关容器的速度效能和空间效能。

我将比较Visual C<span class="token operator">++</span>，Borland C<span class="token operator">++</span>，GNU C<span class="token operator">++</span>标准库中的allocator，
并深入探索其中最精巧的GNU C<span class="token operator">++</span> allocator的设计。    
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p><strong>⏳第三講：malloc/free</strong></p> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>VC6和VC10的malloc比较<span class="token number">96</span><span class="token operator">-</span><span class="token number">97</span>
Small Block Heap （ SBH ）初始化<span class="token number">98</span><span class="token operator">-</span><span class="token number">99</span>
SBH行为分析–区块大小计算<span class="token number">100</span><span class="token operator">-</span><span class="token number">104</span>
SBH行为分析–数据结构<span class="token number">105</span><span class="token operator">-</span><span class="token number">107</span>
SBH行为分析–分配详细图解<span class="token number">108</span>
SBH行为分析–分配<span class="token operator">+</span>释放连续动作图解<span class="token number">109</span><span class="token operator">-</span><span class="token number">115</span>
SBH检讨<span class="token number">116</span><span class="token operator">-</span><span class="token number">122</span>

malloc<span class="token operator">/</span>free是所有内存管理手段的最后一来<span class="token punctuation">;</span>
通过它才和操作系统搭上线。
    
当然你也可以直接调用system API，但不建议。
因此理解malloc<span class="token operator">/</span>free的内部管理至为重要。
我将以Visual C<span class="token operator">++</span>的CRT （C RunTime Library）所带的malloc<span class="token operator">/</span>free源代码为基础，深度探索这最基础最关键的内存分配与释放函数    
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p><strong>⏳第四講：Loki::allocator</strong></p> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>上中下三個 classes 分析 <span class="token number">127</span>
Loki：：allocator行为图解<span class="token number">128</span><span class="token operator">-</span><span class="token number">134</span>
<span class="token keyword">class</span> <span class="token class-name">Chunk</span> 分析 <span class="token number">135</span><span class="token operator">-</span><span class="token number">137</span>
<span class="token keyword">class</span> <span class="token class-name">FixedAllocator</span> 分析 <span class="token number">138</span><span class="token operator">-</span><span class="token number">140</span>
Loki<span class="token operator">::</span>allocator 检讨 <span class="token number">141</span>

即使知名如GNU C<span class="token operator">++</span> pool allocator，也有其小缺陷。

Loki （一套作风前沿的程序库）的allocator设计精简功能完整几无缺点，很值得我们深究。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p><strong>⏳第五講：Other Issues</strong></p> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>GNU C<span class="token operator">++</span> 对 allocators 的描述 <span class="token number">144</span><span class="token operator">-</span><span class="token number">149</span>
VS2013标准分配器与new_allocator <span class="token number">150</span>
G4<span class="token punctuation">.</span><span class="token number">9</span> 标准分配器 new_allocator <span class="token number">151</span>
G4<span class="token punctuation">.</span><span class="token number">9</span> malloc_allocator <span class="token number">152</span>
G4<span class="token punctuation">.</span><span class="token number">9</span> array_allocator <span class="token number">153</span><span class="token operator">-</span><span class="token number">155</span>
G4<span class="token punctuation">.</span><span class="token number">9</span> debug_allocator <span class="token number">156</span>
G4<span class="token punctuation">.</span><span class="token number">9</span> _pool_alloc <span class="token number">157</span><span class="token operator">-</span><span class="token number">159</span>
G4<span class="token punctuation">.</span><span class="token number">9</span> bitmap_allocator <span class="token number">160</span><span class="token operator">-</span><span class="token number">170</span>
G4<span class="token punctuation">.</span><span class="token number">9</span> 使用 G4<span class="token punctuation">.</span><span class="token number">9</span> 分配器 <span class="token number">171</span><span class="token operator">-</span><span class="token number">172</span>
    
除了std<span class="token operator">::</span>allocator，GNU C<span class="token operator">++</span>还带不少allocators，它们不是标准库的一部分，可视为标准库的扩充。
    
我将探讨这些扩充的allocator，特别是bitmap allocator
我们谈的不只是应用，还深入设计原理与实现手法。
    在理解了这么多底层（Windows Heap，CRT malloc<span class="token operator">/</span>free，C<span class="token operator">++</span> <span class="token keyword">new</span><span class="token operator">/</span><span class="token keyword">delete</span>，C<span class="token operator">++</span> allocators ）之后，
也许你终於恍然大悟，再不需要自行管理内存了<span class="token punctuation">;</span>
或也许你终于有能力想像，该在何处以何种方式加强内存管理。
    
    
	你将获得整个video课程的完整讲义（也就是video呈现的每一张投影片画面），和一个完整程序包括代码文件<span class="token punctuation">.</span>cpp和可执行文件<span class="token punctuation">.</span>exe。你可以在视听过程中随时停格仔细阅读讲义，细细咀嚼我所绘制的各种示意图和源代码之间的流动路线<span class="token operator">--</span>这的确很需要时间和脑力，却能让你脑洞大开。
    以下这份不算太细致的主题划分，协助您认识整个课程内容，以及在视听过程中正确翻找讲义。内中的编号就是讲义的页码
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><h2 id="🐋重要概念传送门"><a href="#🐋重要概念传送门" class="header-anchor">#</a> 🐋重要概念传送门</h2> <h4 id="分配器（allocators）"><a href="#分配器（allocators）" class="header-anchor">#</a> 分配器（allocators）</h4> <p>我们已经对必要的基础都做了一个理解。</p> <ul><li>扮演的是一个幕后英雄的角色。我们一般是不会直接用到它的，也不建议，就算你经过这个讲解之后，能够用它，不建议你去用它。因为没有需要这么去用它，它是给容器用的。</li> <li>但是它的优劣非常重要，因为你在使用容器呢，你要不断放元素进去，拿出来，因此都会用到内存。而这个分配器的效率好不好，就会影响到你这个容器的效率。这个效率，包括速度和空间的运营。毕竟内存是有限的。</li></ul> <h4 id="operator-new-和malloc"><a href="#operator-new-和malloc" class="header-anchor">#</a> <code>operator new( )</code>和<code>malloc( )</code></h4> <p>有一个观念：所有的分配动作，最终一层层下去，C++、啥的，总之最后都会跑到malloc去，C这个level，CRT，C runtime library所提供了malloc的这个函数。这个函数再根据，它是在Windows底下还是在Linux还是Unix底下，去调用不同的操作系统里面的API，system API，才去真正的内存。</p> <p>所以在标准层面上，最终大家都是跑到malloc去。</p> <p>operator new( )会调用malloc证据在源代码那里。</p> <ul><li>模板特化、偏特化，萃取 traits 技巧</li></ul> <h2 id="✅第1讲-primitives⭐️"><a href="#✅第1讲-primitives⭐️" class="header-anchor">#</a> ✅第1讲-<code>Primitives</code>⭐️</h2> <ul><li>Primitives，基本构件</li></ul> <h2 id="_01-overview"><a href="#_01-overview" class="header-anchor">#</a> 01.Overview</h2> <ul><li><p>首先，恭喜大家选择这门课程：这门课程是个主题很特殊的课程，这个课程是一个主题很特殊的课程，会关注这个话题，说明你的技术层面到了一个层次。有信心把你的层次拔高到一个非常高的境界！谁敢说自己的课程是“万丈高楼”呢？我敢，哈哈。内存在C++领域是如何是分配内存的，最基本的一些工具→如何去管理它（很高阶的）</p></li> <li><p>包括，对于STL（标准库）里面的分配器是如何管理的，</p></li> <li><p>包括，对于最底层的memory和allocation（malloc函数）这个里面是如何管理内存的，我们要很深入的去看他的动作</p></li> <li><p>从这些里面，我们就能清楚的知道，我们到底要不要做内存管理？</p></li></ul> <p>也许，我们印象中，我们认为要做的管理，其实我们用的这些东西，STL函数都已经做到了。这个工程中，你不仅知道这些业界出名的管理器，他们是怎么做到的。</p> <p><strong>检讨</strong>：或许你心中某些管理是不必要做的，因为那些管理已经够了。</p> <p>Memory Management 101，『<code>101</code>』在英文的意思里面是：包罗万象，什么都有</p> <blockquote><p>万丈高楼平地起</p> <p>『源码之前，了无密码』</p></blockquote> <h3 id="_1-1-讲解目录"><a href="#_1-1-讲解目录" class="header-anchor">#</a> 1.1.讲解目录</h3> <ul><li>第1讲（基础工具）<code>primitives adj.原始的;远古的;人类或动物发展早期的;发展水平低的;落后的</code> <ul><li>讲，在C++下动态分配内存，你大概会怎么做？</li> <li>C++語言中对內存相关的所有基礎構件 (constructs)，包括 <code>malloc/free</code>, <code>new/delete</code>, <code>operator new/operator delete</code>, <code>placement new/placement delete</code>，我將探討它們的意义、运用方式和重載方式。並以此开发一個<strong>极小型內存池 (memory pool)</strong></li></ul></li> <li>第2讲、malloc/free（看malloc和free底部的动作）</li> <li>第3讲、std::allocator（看STL（标准库）底部的动作）</li> <li>第4讲、other allocators（其他分配器底部的动作）</li> <li>第5讲、loki::allocator（看，另外一套，我认为非常棒的一个分配器，里面的allocator的动作）</li></ul> <p>希望做到，心中自有“丘壑”，你所做的每一件和内存相关的事情，你心里头都非常清楚，它的来龙去慢？</p> <ul><li>我们整个课程都是垫<strong>基于对源码的理解</strong></li> <li>malloc是个怎么复制的动作呢？因为我看过它的源代码。分配器呢？源代码</li> <li>因为，代码很大，我尽可能的将代码的动作，画成图</li></ul> <h3 id="ppt-你应该具备的基础"><a href="#ppt-你应该具备的基础" class="header-anchor">#</a> PPT.你应该具备的基础</h3> <ul><li>曾经动态分配并使用memory</li> <li>曾经使用过C++标准库的容器（containers）</li></ul> <h4 id="（2）基础要求"><a href="#（2）基础要求" class="header-anchor">#</a> （2）基础要求</h4> <p>曾经动态分配和使用memory，鲁裰使用疆C++熛蹒庳的容器(containers)。其实技术发展到现在，其实很希望大家直接用标准库中的容器。不用再关关心到内存了，当然我们很希望大家知道里面的工作，来龙去脉。心中有图<strong>不同的编译器，所带的标准库里面的“容器”，它背后的分配器的做法都不一样！</strong></p> <p>所以，当你深入了解这个之后，你就可以选择哪一套分配器来作为容器的支撑，效率会更好？</p> <h3 id="ppt-我们的目标"><a href="#ppt-我们的目标" class="header-anchor">#</a> PPT.我们的目标</h3> <ul><li>从平地到万丈高楼</li> <li>从最基础的C++语言构件（哪些基本的工具，new，malloc等）一直到高知名度的内存管理器</li> <li>彻底了解高高低低的方方面</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721222802645.png" alt="image-20210721222802645"></p> <ul><li>由于这门课程是深入到那些“<code>library</code>”那些库，以及C函数<code>malloc</code>的底部实做。所以，我们真正自己手上要做的什么事情，不太多。但反而是，你手上有我要带你去看的，这些知名的管理器的源代码，对你有帮助。我们自己要写的代码倒是不太多。我目前在用这个来，是因为它背后带着，<code>GNU C</code>的标准库，所以，当我在分析它的分配器的做法的时候，你也有机会，如果有一套这个东西，什么版本其实无所谓，你手上有这个东西，你也可以像我这样去看它的源代码。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721222828232.png" alt="image-20210721222828232"></p> <ul><li>然后，就是<code>VC6.0</code>,注意是<code>6.0</code>，<strong>原因是，后面要带你看malloc的动作，而我看的是VC6.0的源代码</strong>。这个<code>malloc并不属于C++的一部分</code>，而是属于更低阶的C的一部分，叫作（<code>CRT c runtime library</code>里面的东西）</li> <li>我们看得到这个东西吗？可以的，你手上的编译器，VC一定带着一个，通常放在一个叫作<code>CRT</code>这样的子目录底下。更加版本的呢？它的行为和里面的原理，其实都在，这是非常核心的东西，万变不离其宗，但是可能会被包裹得更加晦涩一些，以致于你不容易找。</li> <li>当然你手上没有这些源代码也没有问题，如果是VC6.0那就比较OK了</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721222856257.png" alt="image-20210721222856257"></p> <h3 id="_1-4-参考站点"><a href="#_1-4-参考站点" class="header-anchor">#</a> 1.4.参考站点</h3> <ul><li><p>网上还有更多资料<a href="http://gee.cs.oswego.edu/" target="_blank" rel="noopener noreferrer">http://gee.cs.oswego.edu/<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p></li> <li><p>这个人，从1986年就潜心研究malloc的算法？我们这门课程，<code>malloc</code>占有很重要的角色。因为，你等下就会看到一张图，所有的内存管理动作，最终都跑到malloc上面来。无一例外。所有malloc的行为模式和效率很重要。</p></li> <li><p>目前Linux下的<code>Glibc</code>里面的<code>malloc</code>就是直接来自这个人的产物。</p></li></ul> <p>**而我，要带你看的是VC的版本！（不是那么和这个完全一样，但是其实很多相同，所以懂了VC之后，再去看GNUC下面的做法，就会轻松很多，很多手法是想通的）**但是，malloc太复杂了，它的文章只是包括<code>5-10%</code>，所以，如果你想把这个弄清楚，真的需要看源代码</p> <ul><li>但是，我现在已经走过了这段痛苦的路了。现在可以把心得给你展现</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721222924119.png" alt="image-20210721222924119"></p> <p><strong>谈论到内存的书籍很少，非常少，比如malloc这么重要的东西，世界上没有一本书在讲这个东西！一本都没有，所以，必须追踪源代码！</strong></p> <ul><li><p>《<code>STL源码剖析</code>》中，第2章，有对分配器（GNUC底下的分配器，有很深入的探讨，有很多图）</p></li> <li><p>《<code>modern C++ Design</code>》里面，第4章，在探讨这个<code>loki::allocator</code>里面的分配器，这本书<strong>整个在讲Loki</strong>，Loki，并不是一个专门在做内存管理。内存管理只是其中一小部分。</p></li> <li><p>《small Memory software》不是针对某个产品。是比较广泛和抽象的，所以，不会那么具体的能够对你带来关注。</p></li></ul> <p>这们课程，除了自己要找网络资源和找书，还会带你看很多的知名的library，如下这些都是他看过的源代码。</p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>Libraries :
STL Allocators
-MFC CPlex+CFixedAllocBoost.Pool
&gt;Loki SmallObjAllocatorvC malloc/free
 jemalloc
tcmalloc
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>你将获得的代碉<code>Test-Mem.cpp</code>内有出现於本征羲中的所有代礁。随着这个课程，是不是叫这个名字的cpp，我不知道，或许后面会改个名字。</p> <h3 id="ppt-你将获得的代码"><a href="#ppt-你将获得的代码" class="header-anchor">#</a> PPT.你将获得的代码</h3> <ul><li><code>Test-Mem.cpp</code></li> <li>内有出现于本讲义中的所有代码</li></ul> <h2 id="_02-内存分配的每一层面『图好』✅"><a href="#_02-内存分配的每一层面『图好』✅" class="header-anchor">#</a> 02.内存分配的每一层面『图好』✅</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721222952026.png" alt="image-20210721222952026"></p> <ul><li>天宝当年『查阅是唐朝最盛世期间。』，从以前到现在好像大家可以喘口气。下图，绝大部分程序都在<code>C++ Application</code>层次。当你需要内存的时候，可能用<code>malloc</code>那层，然后下面有很多大家不熟悉的了</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223012686.png" alt="image-20210721223012686"></p> <ul><li><p>C++primitives，这些都是C++提供的一些基本工具。</p> <ul><li><code>new</code></li> <li><code>new[]</code>这个叫array new，大家要创造数组的时候使用，这个大家也还熟悉</li> <li><code>new()</code>这个很多人不熟悉了</li> <li><code>::operator new()</code>这个也不知道</li></ul></li> <li><p>大家使用容器的时候，可能没有感受到内存，但是其实，底层使用了allocator<strong>当然，你也可以、也可能，去调用操作系统提供的内存的，系统调用</strong></p></li> <li><p>Windows底下叫作<code>HeapAlloc</code>，或者更底层的有<code>VirtualAlloc</code>。当然，我们写应用程序，一般不会写这么低阶的，这么写，你的程序就不带有可移植性。和OS绑定死了</p></li> <li><p>『『<font style="background:yellow;">而下面这个呢，我有一门课程</font>』』：来探讨，在Windows底下，对内存的管理（但是，我也没看懂他讲OS的课在哪？？）我们目前这个课程是定位在OS的API之上几层。</p></li></ul> <h3 id="ppt-c-memory-primitives"><a href="#ppt-c-memory-primitives" class="header-anchor">#</a> PPT.C++ memory primitives</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223033141.png" alt="image-20210721223033141"></p> <table><thead><tr><th>分配</th> <th>释放</th> <th>类属</th> <th>可否重载</th></tr></thead> <tbody><tr><td>malloc()</td> <td>free()</td> <td><code>C函数（CRT）</code></td> <td>不可以</td></tr> <tr><td>new</td> <td>delete</td> <td><code>C++表达式</code>（expression）</td> <td><font style="background:yellow;">不可以</font>（？不是好像有运算符重载？其实，不建议重载这2个运算符）</td></tr> <tr><td><code>::operator new()</code></td> <td><code>::operator delete()</code></td> <td>C++函数</td> <td>可（这是<strong>全局</strong>的函数）</td></tr> <tr><td><code>allocator&lt;T&gt;::allocate()</code></td> <td><code>allocator&lt;t&gt;::deallocate()</code></td> <td>C++标准库</td> <td>（这个不能叫作重载。。你可以自己设计一个，然后用简单的语法，让容器使用你的）你可自由设计并以之搭配任何容器（注意，这个是VC下的底层接口，但是GNU C不是的）</td></tr></tbody></table> <ul><li>备注：我看到《C++ primer》上new这个运算符是可以重载的，方式是重载</li> <li>重点理解—内存基本工具：</li> <li>这些东西，在这章做了一个表格分类，你可以直接调用的手上的primitives的工具</li> <li><strong>上面4个。被视频归类为内存基本工具</strong>，分配器里面，有2个最重要的函数，一个叫<code>allocate</code></li></ul> <h2 id="_03-四个层面的基本用法"><a href="#_03-四个层面的基本用法" class="header-anchor">#</a> 03.四个层面的基本用法</h2> <blockquote><p><strong>接下来，我们把上面4个东西都用一遍</strong></p></blockquote> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223101401.png" alt="image-20210721223101401"></p> <ul><li>四个层面的基本用法</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code><span class="token keyword">void</span><span class="token operator">*</span> p1 <span class="token operator">=</span> <span class="token function">malloc</span><span class="token punctuation">(</span><span class="token number">512</span><span class="token punctuation">)</span><span class="token punctuation">;</span>	<span class="token comment">//512 bytes，很低阶动作的用法</span>
<span class="token function">free</span><span class="token punctuation">(</span>p1<span class="token punctuation">)</span><span class="token punctuation">;</span>

complex<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token operator">*</span> p2 <span class="token operator">=</span> <span class="token keyword">new</span> complex<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">;</span> <span class="token comment">//one object，操作符new的使用『new expression』『底层调用operator new』</span>
<span class="token keyword">delete</span> p2<span class="token punctuation">;</span>             <span class="token comment">//不用的时候，我们就把内存收回去了，delete还了，但是其实不是还给操作系统，但简单认为</span>

<span class="token keyword">void</span><span class="token operator">*</span> p3 <span class="token operator">=</span> <span class="token operator">::</span><span class="token keyword">operator</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token number">512</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//512 bytes， 大家比较陌生的。，这是特殊的函数，这是一个全局的函数，这个东西；里头就是调用malloc，（作者告诉的）</span>
<span class="token operator">::</span><span class="token keyword">operator</span> <span class="token keyword">delete</span><span class="token punctuation">(</span>p3<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//里头就是调用的free，里头啥意思？（因为看过源代码）</span>


<span class="token comment">//下面是3个编译选项</span>
<span class="token comment">//以下使用 C++ 标准库提供的 allocators。</span>
<span class="token comment">//其接口虽有标准规格，但实现厂商並未完全遵守；下面三者形式略異。</span>
<span class="token comment">//不管他几家做法不一样，无所谓，但是他们的接口，应该对于使用者要一样？？？</span>
<span class="token comment">//但是很不幸，这几个接口就不一样、、、、、、、、、、、（这或许是作者告诉我们，虽然看了源代码会这么写，但是，我们需要不建议，自己用内部的这些接口？还有1个原因，你观察到下面的allocator，有需要精确的知道分配了多少，释放的时候，，也要告诉，这种写法，需要封装或者你自己记忆，这个一般用容器做得到）</span>

<span class="token comment">//VC上的写法</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">_MSC_VER</span></span>
    <span class="token comment">//以下兩函數都是 non-static，定要通過 object 調用。以下分配 3 個 ints.</span>
    <span class="token keyword">int</span><span class="token operator">*</span> p4 <span class="token operator">=</span> allocator<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">allocate</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
    allocator<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">deallocate</span><span class="token punctuation">(</span>p4<span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>           
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>


<span class="token comment">//BorlandC上写法</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">__BORLANDC__</span></span>
    <span class="token comment">//以下兩函數都是 non-static，定要通過 object 調用。以下分配 5 個 ints.</span>
    <span class="token keyword">int</span><span class="token operator">*</span> p4 <span class="token operator">=</span> allocator<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">allocate</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
    allocator<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">deallocate</span><span class="token punctuation">(</span>p4<span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>


<span class="token comment">//接下来，我们看GNUC 4.9版本的分配器的代码是下面这样，和上面的</span>

<span class="token comment">//12分钟，和2.9比较，它给分配器换了名字，用法也一样了，换得像标准用法看齐了！！！</span>

<span class="token comment">//GNU C 上写法，但是注意，这个写法是早期的版本，当时的写法，这是当时测GNU 2.9版本的时候的</span>
<span class="token comment">//所以，代码可不能这么写，后面不知道哪一班开始的，换了一个名称和调用方式，和上面，“BorlandC上写法”完全一样。</span>
<span class="token comment">//</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">__GNUC__</span></span>
    <span class="token comment">//以下兩函數都是 static，可通過全名調用之。以下分配 512 bytes.</span>
    <span class="token comment">//void* p4 = alloc::allocate(512); </span>
    <span class="token comment">//alloc::deallocate(p4,512);   </span>
    
    <span class="token comment">//以下兩函數都是 non-static，定要通過 object 調用。以下分配 7 個 ints.    </span>
	<span class="token keyword">void</span><span class="token operator">*</span> p4 <span class="token operator">=</span> allocator<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">allocate</span><span class="token punctuation">(</span><span class="token number">7</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
    allocator<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">deallocate</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token operator">*</span><span class="token punctuation">)</span>p4<span class="token punctuation">,</span><span class="token number">7</span><span class="token punctuation">)</span><span class="token punctuation">;</span>     
	
<span class="token comment">//由于alloc那个版本，虽然是2.9的版本，但是他的设计很巧妙，这个巧妙的东西，到新的版本换了一个名字</span>
<span class="token comment">//也就是下面这个样子。pool alloc，内存池</span>
    <span class="token comment">//以下兩函數都是 non-static，定要通過 object 調用。以下分配 9 個 ints.	</span>
	<span class="token keyword">void</span><span class="token operator">*</span> p5 <span class="token operator">=</span> __gnu_cxx<span class="token operator">::</span>__pool_alloc<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">allocate</span><span class="token punctuation">(</span><span class="token number">9</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
    __gnu_cxx<span class="token operator">::</span>__pool_alloc<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">deallocate</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token operator">*</span><span class="token punctuation">)</span>p5<span class="token punctuation">,</span><span class="token number">9</span><span class="token punctuation">)</span><span class="token punctuation">;</span>	
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223131127.png" alt="image-20210721223131127"></p> <h3 id="_3-1-『内存池』✅"><a href="#_3-1-『内存池』✅" class="header-anchor">#</a> 3.1.『内存池』✅</h3> <p>pool是个内存池，我们很习惯用这个字眼。内存好像一个池塘，为何当初叫作内存池？？没有继续深究。后面会告诉你什么是“内存池”。<strong>我们做内存管理都是用内存池的概念来做管理。</strong></p> <h2 id="_04-基本构件之一new-delete-expression-上"><a href="#_04-基本构件之一new-delete-expression-上" class="header-anchor">#</a> 04.基本构件之一<code>new/delete expression</code>(上)</h2> <h3 id="重点『区别new-expression』✅"><a href="#重点『区别new-expression』✅" class="header-anchor">#</a> 重点『区别new expression』✅</h3> <p>为什么画图的时候，说<code>new</code>和<code>::operator new()</code>底下是用的<code>malloc</code>呢？</p> <p>区别三个：</p> <table><thead><tr><th>3种的区别</th> <th></th></tr></thead> <tbody><tr><td>new</td> <td>底层先调用<code>::operator new</code>分配内存，然后调用析构函数（new expression，<font style="background:yellow;">new表达式，有的人/书上叫new operator！『说的《C++ primer》233』，new操作符，侯捷说这个容易让人困惑</font>，但是其实，重点在operator这，这好像是很多书籍最喜欢的东西！）</td></tr> <tr><td><code>::operator new</code></td> <td>它的底层是调用的malloc，这是个<strong>全局函数（注意是函数！！）</strong>，所以才是<code>::</code>,注意：<strong>（operator new（）也可以？？课件上这部分没讲解清楚？？4分钟，重看？？</strong>），<strong>如果你的那个类的没有去重载这个函数，所以，这一行，就自然而言调用全局的版本</strong></td></tr> <tr><td></td> <td>好像，是作者的原因，STL源代码剖析P49用的<code>::operator new</code>,然后 前面演示4种方法用的<code>::operator new()</code>，然后写课程用的operator new()（3种全是指的这个全局的函数。。。上面显示了，在全局命名空间的::可以省略？？是不是呢？？）</td></tr> <tr><td><code>placement new</code></td> <td>new(p)Complex(1,2)</td></tr></tbody></table> <p>PPT中提到一个神奇的编程：</p> <p>构造函数不能被直接调用（但是，VC6,0编译器不严谨，似乎new底层的2步骤实现，可以那样）但是，析构函数可以被直接调用。</p> <p><strong>测试程序</strong></p> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span><span class="token string">&lt;bits/stdc++.h&gt;</span></span>
<span class="token keyword">using</span> <span class="token keyword">namespace</span> std<span class="token punctuation">;</span>

<span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
	
	string <span class="token operator">*</span>pstr <span class="token operator">=</span> <span class="token keyword">new</span> string<span class="token punctuation">;</span>
	cout <span class="token operator">&lt;&lt;</span><span class="token string">&quot;str= &quot;</span> <span class="token operator">&lt;&lt;</span><span class="token operator">*</span>pstr <span class="token operator">&lt;&lt;</span>endl<span class="token punctuation">;</span>
	<span class="token comment">// i pstr-&gt;string : : string(&quot;ijhou&quot; );</span>
	<span class="token comment">// [ Error] 'ctass std::basic_string&lt;char&gt;' has no member named 'string‘</span>
	<span class="token comment">//pstr-&gt;~string(); //crash</span>
	cout <span class="token operator">&lt;&lt;</span> <span class="token string">&quot;str= &quot;</span> <span class="token operator">&lt;&lt;</span> <span class="token operator">*</span>pstr <span class="token operator">&lt;&lt;</span> endl<span class="token punctuation">;</span>

	
	<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>注意，上面错误神奇吧！！</p> <ul><li><code>std::basic_string&lt;char&gt;</code>为什么是这个class呢？</li> <li>为什么不是string呢？因为string在STL中是个typedef，是换了个名称，真正名字是<code>:basic_string&lt;char&gt;</code>，crash哪行其实可以执行成功，但是会crash（ 程序崩溃掉，因为不对应嘛！）</li> <li>所以，为了测试这个，作者做了那个A类，测试到底能不能被，使用通过指针调用构造和析构函数。VC6.0能调用构造和析构。GNU C不可以调用构造函数，技术上表现严谨，VC6.0太宽松了。上面习惯，测试习惯，把各个单元放在一个命名空间里面。这样，各个单元就非常独立。</li></ul> <h2 id="_05-基本构件之一new-delete-expression-中"><a href="#_05-基本构件之一new-delete-expression-中" class="header-anchor">#</a> 05.基本构件之一<code>new/delete expression</code>(中)</h2> <h3 id="ppt-new-delete-expression被编译器转为『3个操作』✅"><a href="#ppt-new-delete-expression被编译器转为『3个操作』✅" class="header-anchor">#</a> PPT.<code>new/delete expression</code>被编译器转为『3个操作』✅</h3> <p><font style="background:yellow;">所以，可能『侯捷』和《C++ primer》上说的不一样</font>，『侯捷说new不能重载，可能是想说，new expression转换后的步骤，不能改变！！必须是这3个操作！』</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223209001.png" alt="image-20210721223209001"></p> <ul><li>记住下面</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223233497.png" alt="image-20210721223233497"></p> <h2 id="_06-基本构件之一new-delete-expression-下"><a href="#_06-基本构件之一new-delete-expression-下" class="header-anchor">#</a> 06.基本构件之一<code>new/delete expression</code>(下)</h2> <ul><li>这个说的，好像就是我们前面写的string模板的new</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223310158.png" alt="image-20210721223310158"></p> <h2 id="_07-array-new和array-delete『另一种new-expression』"><a href="#_07-array-new和array-delete『另一种new-expression』" class="header-anchor">#</a> 07.<code>Array new和Array delete</code>『另一种new expression』</h2> <p>先前有个问题的：<code>placement new</code>是什么鬼？（网上有博客园说<code>placement new()</code>函数是不可以被重载的）</p> <blockquote><p>自我反思：好像博客园的是错误的！</p></blockquote> <h3 id="_7-1-『带-不带指针的class引入的坑』✅"><a href="#_7-1-『带-不带指针的class引入的坑』✅" class="header-anchor">#</a> 7.1.『<code>带/不带指针的class</code>引入的<code>坑</code>』✅</h3> <ul><li>牛客上配套的习题！vivo考过『<a href="https://www.nowcoder.com/test/question/done?tid=44172669&qid=301275#summary" target="_blank" rel="noopener noreferrer">传送门<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>』</li></ul> <blockquote><p>我的<strong>思考如下</strong>：</p></blockquote> <ul><li>坑的原因之一是：<font style="background:yellow;">free的底层原理</font></li> <li><font style="background:yellow;">（1）不带指针的class</font>，对应<code>array new</code>的时候，使用单个<code>delete</code>也不会造成内存泄漏！！<strong>原因是：free是借助<code>cookie</code>来释放的！</strong></li> <li><font style="background:yellow;">（2）带指针的class</font>，对应<code>array new</code>的时候，<code>delete p</code><strong>会造成内存泄漏！</strong> <ul><li>原因是：free是借助<code>cookie</code>来释放的！！但这也只能保证，你这些class本身被清理，但是由于不调用『足量的』<code>array delete</code>，所以，就<code>不会调用足量的『析构函数』</code>，就不会把内部指针指向的内容给清理，造成内存泄漏！原因：我们会把内部指针指向的内容，在『析造函数』中进行清理！！</li></ul></li> <li>（3）但是为了编程统一，当然以最严格的要求！！
<ul><li>此外，还有个原因：万一，尽管我们的析构函数不一定有那个指针，但是它如果提示一些很重要的信息，那我们如果不这么写，可能就会以为错误。事与愿违？</li></ul></li></ul> <blockquote><p>思路如上。</p></blockquote> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223342868.png" alt="image-20210721223342868"></p> <h3 id="_7-2-记得『new-expression还包括：array-new』✅"><a href="#_7-2-记得『new-expression还包括：array-new』✅" class="header-anchor">#</a> 7.2.记得『new expression还包括：array new』✅</h3> <ul><li><font style="background:yellow;"><code>array new</code>指的是 <code>new []</code>，当然这些个也都归类为表达式（expression）</font>，显然叫这个名字，是为了去建造一整个array（数组）的对象，比如</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>A <span class="token operator">*</span> p<span class="token operator">=</span> <span class="token keyword">new</span>  A<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">delete</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>p<span class="token punctuation">;</span>
<span class="token comment">//唤起3次dtor(析构的简写)</span>
<span class="token comment">//对于初学者很喜欢delete p不加中括号，然后很惨，加不加的影响还是很大的</span>

如果你没有写<span class="token punctuation">[</span><span class="token punctuation">]</span>，那么这个编译器，背后就不知道，你这个指针指的是array，它就会只调用<span class="token number">1</span>次
下面解释的图，画得超级好
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223415609.png" alt="image-20210721223415609"></p> <ul><li>上面在GNU C编译器中，<code>array new</code>是自上而下，<code>array delete</code>是自下网上。</li></ul> <h3 id="_7-3-『上下cookie设计』✅"><a href="#_7-3-『上下cookie设计』✅" class="header-anchor">#</a> 7.3.『上下cookie设计』✅</h3> <ul><li>cookie是个很大的重点</li> <li><font style="background:yellow;">cookie设计，free准确释放内存的关键</font></li> <li><font style="background:yellow;">后面内存管理的时候，很大一个诉求是围绕这个cookie。</font></li> <li>这个cookie的存在，以及多大，我们现在要理解的</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223457650.png" alt="image-20210721223457650"></p> <p>注意：</p> <ul><li>free只拿到一个cookie是一些琐碎的东西。（一些book keeping，簿记的一些琐碎的东西，其实最重要的就是———<strong>记录整块（它指的3个对象）的长度</strong>，因为这一块，最底层是malloc给我们的，对应的是用free去回收他们，free只是拿到一个指针，它怎么知道这块多大？</li> <li>但是没人告诉他，所以malloc和free设计就说好了，那<strong>我分配给你的时候，你带着一个小东西就好了，里面记录这个长度，这个设计是malloc和free在所有的平台上，所有的C++编译器都是这么设计的，这个叫cookie，非常重要的一个东西</strong>。）</li> <li>注意，上面3个如果只析构一个，<strong>在不同平台实现不一样，有的析构第1个，有的析构第3个！！</strong></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223526592.png" alt="image-20210721223526592"></p> <ul><li>上面的图，是在VC6.0底下，观察malloc给我们的内存的布局，这图很宝贵。是看了很多琐细的代码整理出来的，当然更新的版本是不是这样？我没有去追究，但是这些很核心的部分，我认为不会改动。</li> <li>在其他平台上，比如GNU C上，它的布局也许会有点变化，但是它的原理是不会变的，它<code>一定会带着cookie</code>。现在解释cookie，浅尝辄止。因为后面第3讲，有1个主题专门在讲malloc。到时候讲这个地方会很清楚！！！</li> <li><code>上面浅黄色的，只有在debug模式的时候会出现。（这2个东西大小非常确定，32个B，还有4个B）</code></li> <li>关于最上面和最下面各有cookie，我习惯叫他们<code>上cookie</code>和<code>下cookie</code>。</li></ul> <h3 id="_7-4-关于61h本来是60h，为什么是61h"><a href="#_7-4-关于61h本来是60h，为什么是61h" class="header-anchor">#</a> 7.4.关于61h本来是60h，为什么是61h</h3> <p>因为1 是开关。</p> <ul><li>上cookie负责记录整块（包括了额外的大小？？所以才是61h？？)的大小，然后要额外负担一些，加完之后，还要调整到16的边界，因为在VC6.0上面，有这个要求（内存对齐？？？）所以，你在VC下获得的区块，（有些你看不见）全部加起来是16的倍数。所以，还要一个叫<code>pad的东西（填补物）</code></li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code><span class="token keyword">int</span> <span class="token operator">*</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">delete</span> p<span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><ul><li>上面这种，int的例子，其实是没有影响的，**因为int没有所谓的析构函数！**所以，对它来讲，<code>调用1次『不足量的』还是10次『足量的』的析构函数</code>，一点影响都没有。所以，对于int，加不加括号无所谓的。比如，<strong>前面我们写的类的，析构函数也没有意义，那一块能不能全部回收？？是可以的！</strong>（注意！）在那种情况，也不会有内存泄漏！</li> <li>（后面的Demo类，<strong>如果析构有意义，那就不一样了</strong>，<font style="background:yellow;">原因：如果析构有意义，那么那个内存布局！多了个3</font>『『20分钟的时候，重新看』』，这下清晰了，<strong>就是因为那个3，才会导致这种会“内存泄漏”，因为还没有往上看到free的大小是多大</strong>，懂了，这样，前面说不会“内存”泄漏，这下知道了，底层free就会）（什么鬼。）但是，如果，你放的是object，并且这个obeject它的析构函数是有意义的， 并且是重要的。</li></ul> <h2 id="_08-replacement-new"><a href="#_08-replacement-new" class="header-anchor">#</a> 08.Re<code>placement new</code></h2> <p>我们的目标是：把C++这些基本构件，有关内存的这些基本工具，通通弄清楚。然后，我们一个个来重载啊它。</p> <h3 id="_8-1-我对分类的思考✅"><a href="#_8-1-我对分类的思考✅" class="header-anchor">#</a> 8.1.我对分类的思考✅</h3> <blockquote><p>我们现在手上有『『3个C++给的工具』』</p></blockquote> <ul><li><code>new</code></li> <li><code>array new</code></li> <li>第3个是<code>placement new（现在说）</code></li> <li>『『<font style="background:yellow;">点评：我总感觉，<code>operator new</code>的变种就是<code>placement new</code>，？？感觉侯捷这个分类有问题</font>』</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210721223619505.png" alt="image-20210721223619505"></p> <ul><li><code>placement new</code>的形式，我们在前面看到了，是这样</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>Complex<span class="token operator">*</span> pc<span class="token operator">=</span><span class="token keyword">new</span><span class="token punctuation">(</span>buf<span class="token punctuation">)</span><span class="token function">Complex</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>作用是：placement (对人的)安置，安排;;(对物件的)安置，放置</p> <p>『『重要』』<font style="background:yellow;">允许我们将对象，建构在构造于<strong>已经分配</strong>的内存中。</font>所以，手上一定要有一根指针，代表那个已经分配好的内存。</p> <ul><li>上面的形式，意思是说：我要创建一个对象，这个对象呢，把我创建在这个（buf)位置上。（当然，这个位置是已经分配好了的，不然咋们会出错，逻辑就不对了），因此你可以想象在这个placement new 里面其实已经不需要分配内存了。</li> <li>它给出来这个形式的意思告诉我们，它不会再去分配内存了，所以，我喜欢把它翻译成（<code>placement new</code>，<code>定点的new</code>）</li> <li>然后，我们看下面的编译器翻译的代码，发现和new不一样，那肯定。发现，多了第2个参数，buf。从源代码看来，placement new就等同于，调用构造函数。</li> <li>注意点：<font style="background:yellow;">没有所谓的placement delete，因为，placement new根本就没有分配memory</font></li></ul> <h3 id="_8-2-『术语争议』"><a href="#_8-2-『术语争议』" class="header-anchor">#</a> 8.2.『术语争议』</h3> <ul><li>注意！『侯捷说：没有所谓的placement delete』</li></ul> <p><font style="background:yellow;">因为<code>placement new</code>根本<strong>没有分配内存</strong>！！但是也有人说，写一个<code>placement new</code>也要对应的delete，我们称那个叫<code>placement delete</code>，<strong>也有这种讲法</strong>。额，能理解（这是大家术语上的分歧。。）『此处，我支持侯捷的观点』</font></p> <ul><li>关于，placement new到底是什么东西呢？？</li> <li>不去讲术语，我们来讲代码的话。</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>或者指的 <span class="token keyword">new</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span>		比如我们前面的Complex<span class="token operator">*</span> pc<span class="token operator">=</span><span class="token keyword">new</span><span class="token punctuation">(</span>buf<span class="token punctuation">)</span><span class="token function">Complex</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
或者指的 <span class="token operator">::</span><span class="token keyword">operator</span> <span class="token keyword">new</span><span class="token punctuation">(</span>size<span class="token punctuation">,</span> <span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  额，这个不是底层的了吗
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h2 id="_09-重载"><a href="#_09-重载" class="header-anchor">#</a> 09.重载</h2> <blockquote><p>目标：<strong>精确控制</strong>！！</p></blockquote> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>在理解了手上3把刀子之后。
应该带着你去看，如何重新定义他们，重载（overloading）他们。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072012498.png" alt="image-20210722072012498"></p> <ul><li>PPT中，我们要讲的就是如何将路线从，下面的路线转为上面的路线。（视频2&quot;30秒）如果你有重载它，就会走1的路线（所谓内存管理，就是将动作接管过来到这来，比如弄个内存池，玩一大块，然后切成小块，或许速度上跟高，空间上也更省（什么叫这个？？因为我们希望去除我们前面讲到的cookie，因为一块内存上下有2块，耗用了8个字节，如果有一百万个或者元素，额外开销就很大，当然最终还是要下去，然后最后到malloc和free），如果没有，走2路线。</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>FOO<span class="token operator">::</span><span class="token keyword">operator</span> <span class="token keyword">new</span><span class="token punctuation">(</span>size_t<span class="token punctuation">)</span><span class="token punctuation">;</span>这个是可以重载的
<span class="token operator">::</span><span class="token keyword">operator</span> <span class="token keyword">new</span><span class="token punctuation">(</span>size_t<span class="token punctuation">)</span><span class="token punctuation">;</span>这个也可以重载，但是少见，这个是全局的，重载这个很少见，毕竟这个影响太深远了。。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><ul><li>所以，上面的图，或许告诉我们<code>operator new</code>和<code>::operator new(size_t)</code>不是一个东西？？？？『但我怎么觉得，广义上，就是一个东西。。』我们只有将三把工具接管过来，我们才能更好的去进行内存管理。</li></ul> <h3 id="_9-1-侯捷再次声明『new-expression的概念』✅"><a href="#_9-1-侯捷再次声明『new-expression的概念』✅" class="header-anchor">#</a> 9.1.侯捷再次声明『new expression的概念』✅</h3> <ul><li>PPT中说道，expression（不可改变，不可重载）『我发现，就是我理解的那样，侯捷老师对new操作符的看法并不是和C++ primer的不同，<strong>而是，表示，new被编译器转换后的操作步骤不能变！</strong>！』</li> <li>此处，PPT中表示
<ul><li>member function形式的<code>FOO::operator new(size_t )</code>可以重载</li> <li>global function形式的<code>::operator new( size_t )</code>也可以重载</li> <li>这验证了，侯捷老师在『表格中画的，operator new函数能够重载的意思，，注意，<strong>它刻意没有告知是成员函数还是全局的函数</strong>，我在前面写上仅仅全局是不正确的说法。』</li></ul></li></ul> <h3 id="_9-2-『重载重点』"><a href="#_9-2-『重载重点』" class="header-anchor">#</a> 9.2.『重载重点』</h3> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>
重载<span class="token operator">::</span><span class="token keyword">operator</span> <span class="token keyword">new</span>
<span class="token keyword">inline</span> <span class="token keyword">void</span> <span class="token operator">*</span> <span class="token keyword">operator</span> <span class="token keyword">new</span><span class="token punctuation">(</span>size_t size<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    
<span class="token punctuation">}</span><span class="token punctuation">;</span>

重载Array版本

<span class="token keyword">inline</span> <span class="token keyword">void</span> <span class="token operator">*</span> <span class="token keyword">operator</span> <span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">(</span>size_t size<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072101467.png" alt="image-20210722072101467"></p> <ul><li>侯捷下面是<code>::operator new</code></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072159012.png" alt="image-20210722072159012"></p> <ul><li>右边是全局的operator new的源代码在VC6.0下的12分30秒</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072240554.png" alt="image-20210722072240554"></p> <h3 id="_9-3-各种new的关系"><a href="#_9-3-各种new的关系" class="header-anchor">#</a> 9.3.各种new的关系</h3> <ul><li>如下图的PPT：</li> <li>array new这样的一共表达式
<ul><li>底层调用的是operator new</li></ul></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072324754.png" alt="image-20210722072324754"></p> <ul><li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072401622.png" alt="image-20210722072401622"></p> <h2 id="⏳10-重载示例（上）"><a href="#⏳10-重载示例（上）" class="header-anchor">#</a> ⏳10.重载示例（上）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072516806.png" alt="image-20210722072516806"></p> <ul><li><p>侯捷</p></li> <li><p>侯捷</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072555555.png" alt="image-20210722072555555"></p> <h2 id="⏳11-重载示例（下）"><a href="#⏳11-重载示例（下）" class="header-anchor">#</a> ⏳11.重载示例（下）</h2> <h3 id="_11-1-重载placement-new-✅"><a href="#_11-1-重载placement-new-✅" class="header-anchor">#</a> 11.1.重载placement new ✅</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072704327.png" alt="image-20210722072704327"></p> <ul><li><p>侯捷</p></li> <li><p>侯捷</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072738375.png" alt="image-20210722072738375"></p> <ul><li>侯捷</li> <li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072839134.png" alt="image-20210722072839134"></p> <ul><li>侯捷</li> <li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072908917.png" alt="image-20210722072908917"></p> <h2 id="🐋神奇的开始"><a href="#🐋神奇的开始" class="header-anchor">#</a> 🐋神奇的开始</h2> <ul><li>第1讲，并发展处1个小型的<code>针对每个class（per-class）</code>的自己的<font style="background:yellow;">1个小型分配器</font></li></ul> <h2 id="_12-per-classallocator"><a href="#_12-per-classallocator" class="header-anchor">#</a> 12.<code>Per-class</code>allocator</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722072951779.png" alt="image-20210722072951779"></p> <p>现在我们终于把基本元素的这一些行为。看他的重载的方式，全部都讲过一遍。
这个基本元素是什么呢？利用operate new ，placement new. 啊，还有对应的array new 等等等。</p> <h2 id="『针对一个class』"><a href="#『针对一个class』" class="header-anchor">#</a> 『针对一个class』</h2> <p>终于万事俱备，我们『现在可以开始<code>针对一个class</code>来写出他的内存管理。』让
我们要的是什么事情？
刚刚在前面我找出一个适当的图片出来。我曾经以这一张画面引导你。当使用者假设我现在是类的class 的设计者。
使用者是这么用的。那么你已经写好的这个代码，这样看人。
他最终是调用malloc。</p> <p><strong>大家对malloc有一个误解，会觉得这个大概很慢。</strong></p> <p><strong>其实他一点都不慢。我们将在第三讲里面谈到malloc 的行为。</strong>
好在无论如何，就算他确实比较慢啊，其实他不慢，就算他很慢的话呢呃或不慢。
<strong>无论如何，减少调用malloc的次数总是很好的。</strong>
所以我们会想要：使用者这里如果有很多次很多次的new</p> <ul><li>我们作为这个类classs Fool的设计者，能不能够<strong>先挖一大块来做准备，自己去切一些小块。</strong></li></ul> <p>然后我比如说我现在一次挖1000个，那么你使用者呢，你可以不断的在那边扭，你可能啊好5个8个，100个、300个、500个。我手上有1000个。你要的时候，我总是很快就给你了，我这1000个是用malloc那个用的一次而已，拿到之后切成小块，<strong>所以我在供应的时候，我作为Fool，<strong>我在</strong>供应使用者的时候就很快了，不要每次都调用malloc了</strong>。</p> <ul><li>这是第一个考量，所以我必须接管这个到这个地方来，我要在Fool里面去重载这个函数<code>operator new</code>来接管。</li></ul> <p>做什么事呢？</p> <ul><li><p>这个图可以很好形象来：给你一个感觉。<strong>我就是挖一大块，切成一个一个的用串链把它串起来。这样就是一个小型的内存管理。</strong></p></li> <li><p>那么除了降低malloc的调用次数之外。</p></li> <li><p>我还想降低cookie的用量。</p></li></ul> <p>因为如果我没有特殊设计的话，按照这一个流程看来，一次的Fool就调用一次malloc，一次malloc，我们刚才已经看过了。
一次malloc 就得到两个cookie，或者叫一组，一组8个字节。
我想降低那个次数，个数。</p> <h2 id="『注意这个设计』"><a href="#『注意这个设计』" class="header-anchor">#</a> 『注意这个设计』</h2> <ul><li>所以说回到刚刚我的例子，如果我手上有一次要1000个的大小，这1000个切下来呢，他们都是不带cookie的。</li></ul> <p>只有这一千个的这一整包的上下带的cookie</p> <p>所以内存池的设计就是这一大块啊，这样一个池塘，一个池子，，这一大块设计呢，，<strong>不但是要提升速度，并且要降低浪费率。事实上，内存管理目标就是这两件事情，一个是速度，一个是空间。</strong>
所以刚刚回到我刚刚我们从打算从这里开始：我们手上的工具都有了。</p> <h2 id="『给class设计小型的』"><a href="#『给class设计小型的』" class="header-anchor">#</a> 『给class设计小型的』</h2> <p>终于我们要为这个class，现在这个叫screen 来写小型的内存管理，这是我们迈向分配器的第一步。在整个设计里头呢我有第一步。然后第二步会做的更精巧一些，到了第三步就终于趋近于标准库的分配器了。</p> <p>我们马上来看看你们能马上来看看这个例子。这个例子取材质这一本书里面的第七百六十五页。
我并不打算去把这些变量啊做一些改变。然后当成是我自己设计的例子。
我就是这样也意义不大。我们宁愿保存它的完整面貌，反正只是一个小东西。呃，<strong>现在很流行一句话叫向偶像致敬</strong>。
我们也像这一位非常优秀的作者。
致敬他写的C++ primer 这一系列的书籍好几个版本。
这个例子是这样，好叫做screen。
先看一下他Data
由于刚刚的分析，我们希望挖一大块，而挖一大块的时候，需要指针把它串起来，基于这个考量，我们在原有的data之外再设计一根指针next这个指针将指向自己，这种东西，所以将来就可以做出这个图。</p> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>Screen <span class="token operator">*</span> next<span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>.</p> <p>不过听到这里，你可能就有一个疑惑了。
这个数据是这样，四个字节。为了将来后头的这个内存管理。而多设计一个指针。这样膨胀率是百分之百。指针也是四个字节原来也是四个字节，四变八。两倍百分之百。而得到的成果是什么呢？**得到了成果是这里面：第一个降低malloc的次数。**但我刚刚已经告诉过你了没？那个其实蛮快的。第三讲会提到，所以这个降低malloc调用次数其实影响不太大。</p> <p>第二个诉求是没有cookie可以可以去除。你在这边去除cookie，而这里却为了这件事情而膨胀百分之百，这是一个什么情况呢？当然了，膨胀百分之百，这听起来很可怕，是因为现在原本的数据只有四个字节，<strong>也许这原本的数据是还蛮大的。比如说原本的数据量是一百个字节。那膨胀率当然就变低</strong>了。
<strong>无论如何。总之感觉好像有一个遗憾。为了去除cookie，这边增加了指针。</strong>
你是挖东墙补西墙呢，你还是你到底有没有得到真正的效益？</p> <p>**好，这个事情其实到了第二版本，这个指针是可以不要的。**但是现在是第一版本，我们先让大家感觉一下。</p> <p>好做了这样的设计之后，我现在重载这两个函数<code>operator new</code>，这个前面都提过了这个。他们应该是静态的，但是写不写的无所谓。这两个函数的设计在这里右手。
<strong>使用者去new 一个screen 的时候，。，就被接管那个分配内存的动作，，就被接管到这个函数来。这个里头就去挖一大块，多大快呢？这个设计这里是24。</strong></p> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>screen chunk是常量。是<span class="token number">24</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><strong>这是一个常量，在这里头它是一个常量24</strong>。这边是new 的动作，就这里是真正其实就是malloc。分配内存的动作。他分配多大？这是一个字符所形成的数组，也就是以字节形成的数组多大呢？这个Chunk，Chunk的计算在上面这里。这就是24个，哎，这里是24个元素。每一个元素的大小是这样传进来的，编译器会存进来。
这里就要24个。算好之后，一次性的把它拿到。这边有一些指针的转型。然后把这一大块分割片片，当作链表串接起来。
这里的分割动作我就不带大家去去看的，就是指针的操作跟转型。这一块。最后都切割好之后。</p> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>啊，第一个传回去这里有个<span class="token keyword">return</span> p 。把这个传回去，剩下百分之<span class="token number">24</span>嘛，剩下<span class="token number">23</span>块。
    那么这是一个单向链表，所以永远有一根指针指的头。
    就是这里叫freeStore『注意这个设计：
    
    一开始是<span class="token number">0</span>，经过这个动作之后，这个freeStore 就指向头了。
那第<span class="token number">1</span>一个给出去之后，freeStore就会指向下一个，再给出去就再下一个，这是非常单纯的单向链表的操作。
    
    『所以，这样，我要是连续<span class="token keyword">new</span>几个，那么速度就上去了，因为那个<span class="token keyword">while</span>循环，不一定会用到！！！』
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>我们就不必去提他了。
现在看回收的动作。当使用者去delete 一个screen。。delete 会先调用析构函数，然后调用那个释放内存的函数，这时候释放内存就跑到这个函数来。</p> <h3 id="『我觉得这是设计核心』"><a href="#『我觉得这是设计核心』" class="header-anchor">#</a> 『我觉得这是设计核心』</h3> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>也就是这里。这里会收到一个指针。就把这个指针回收到单向链表之中。单向链表的操作就不是我们的。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><ul><li>重点这个应该是各位要具备的一个基础。<strong>单向链表一定有一个指针指向头</strong>，所以**现在回收一个元素该放到哪里好呢？当然是放到头最快。**那个指针换一换就好了。这就是这里的动作。</li></ul> <p><strong>这就是一个小型的内存池 。这个池呢只针对这一个class 来操作，因为是写在这个class 里头，写在这两个函数里头。</strong>
所以我们把这一种，这种池，这个这个小型的分配器叫做<code>per-class allocator</code></p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073041361.png" alt="image-20210722073041361"></p> <p>这是第1版本。各位拿到的程序，都会包括这些东西。我给你的程序。我们看怎么使用。设计好刚刚的那个东西之后。
这是我的测试。</p> <p>我先测一下这个scream 多大。我们刚刚其实看代码已经知道了一个整数跟一个指针，所以说大小是8，『32位的机子』这边有输出是吧？然后我准备一大堆指针，100根。</p> <p>我是不是100次，对100次的去new 它。输出前十个。比较其间隔。</p> <ul><li>我想确认什么事情呢？</li> <li>我想带你去看看。他们确实没有cookie</li></ul> <p>刚刚已经得到100根指针的，我只打印出前10根指针出来。
结果在这里。最后把它点击的掉。所以我们的重点是看看这前十根指针相差距离。这里是间隔八。</p> <p>右边这个执行结果是什么呢？
左边是向上叶那样写了一个上一页那样得到的结果，<strong>右边是没写的结果『指的是：没有重载operator new』</strong> <strong>没写的话，回到上一页，没有写这两个函数，那么分配或者是释放就都不会经过他，那就是一般正常的情况就会带着cookie好，我们看到在左边间隔八，右边间隔16</strong> <strong>这表示右边确实带的cookie，而且cookie 是多少呢？</strong> <strong>拿VC6,0那个图来做例子。上下有偶有cookie，每个cookie 是四个字节。所以说八个</strong>，你看右边的。
一起左边每一块都多八个字节。
我们前面。这个很前面的我很快的翻过去，他谈到。
曾经看到v c 六，它的区块是这样，但我这个例子不是vc 六。是在GNUC是编译器底下去做了，也是多八个字节。
<strong>的确，我前头已经告诉你了。cookie 这种东西是这种设计方法是，到处都存在的，所有平台都是这么设计。</strong>
好伟大。刚刚的例子来。我们再看一次。执行结果。好，这里其实这样的输出是有一点。要说冒险嘛也不太对，<strong>我的意思是说，如果他间隔不是8，其实也不能够证明什么事情。不过很幸运的，他间隔是八，那太好了</strong>。</p> <ul><li>因为<strong>在在你的系统里面，你连续的分配一块一块的内存，他们故意，他们并不一定会连续在一起</strong>。所以他们到底，当时会在什么地方取决于你的电脑在运作，那可能你的电脑是一个多任务系统，而且还是多线程。呃，这一件事情一分配一块做完之后呢，也许其他的事情或者别的进程插进来。啊，内存用的有点支支离破碎。以至于这十个没有连在一起，这也是有可能的。不过很幸运的，这是一个识别，现在知识连在一起的那就证明了。</li></ul> <p>他们确实不在顾忌，左跟右。
还有，这个例子已经点出了所谓的内存分配，那什么管理的机制就是一个池塘，一大块，这一大块呢多半就是用链表来管理。非常经典的例子。差别呃<strong>比较唯一的缺点就是他多了一根指针</strong>。
所以在下一个例子。我们<strong>马上要来看第二个例子，就把这个指针去除掉了。</strong></p> <h2 id="⏳13-per-class-allocator-2"><a href="#⏳13-per-class-allocator-2" class="header-anchor">#</a> ⏳13.<code>Per-class</code> allocator 2</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073441520.png" alt="image-20210722073441520"></p> <ul><li>书籍那他的第二版第10个条款里头有这么一个例子，我们来看看这个长相！！
现在这个class叫作airplane， Data在哪里？这两个，一个airplaneRep和那是四个字节，type的是一个字节，所以它加起来是五个。的解。不过等一下你会看到啊，这个一般我们定义器都会设定arm的对，齐齐位，所以五会被调整为八。</li></ul> <h3 id="『常见的设计手法』"><a href="#『常见的设计手法』" class="header-anchor">#</a> 『常见的设计手法』</h3> <ul><li>将上面的struct再设计到另一个union中</li></ul> <p>好，<strong>这是他的数据，在这边这个地方特别把它包装成一个struct，这也是一个常见的手法</strong>，这个现在把它叫做average promotion这一段这里又出现一个union，如果你对union不太理解，赶快把c加加数据拿出来复习一下。
你可以这样去想象，有点就是一个东西用多种角度去看它，同一个东西用不同的角度或者说用不同的名称去表现它。
**所以这个union是什么意思呢？？意思是说这里面有两个member。他这个两个member其实是同一块东西，**所以同一块呢一个mbs，就是刚刚你看到的这个5个字节其实总共是八个字节的这个东西。</p> <p>另外一个member意思是你这句话的意思是我要把它看成一根指针，这个指针的名字叫next。所以这里带来一个很重要的观念，我的数据本来是这么大，我现在呃，8个字节五啊五那就会被变成八啊八个字节。但是我换一个角度去看它，我是用指针去解释它，指针是四个字节，等于说本来的八个字节，我现在看的是前四个字节，把它看成一根指针。
<strong>好，注意这种概念：这个叫in beded pointer叫嵌入式指针。</strong>
等一下还会出现这个概念啊，我们先把这个放下来。好，接下来是一些呃，不是重点的东西，</p> <p>再来就是这两个函数这一次加上了<code>static</code>所以我刻意拿这两个版本也有一点点让你比较的意思。刚刚的那个版本。
诶我记得这两个版本有一个是有static，一个没有，可能都被我加上去了。
好，我们再回到这第二版本来。static后面还有一些这两个版本不一样的啊，我都原貌呈现，让你来比较一下就是做细节做法的一些小小不同，但是殊途同归。</p> <h3 id="『常量是block-size』"><a href="#『常量是block-size』" class="header-anchor">#</a> 『常量是Block_size』</h3> <p><strong>继续往下看，这里面定义的一个常量叫512，就是它的内存,内存池里头呢每次要的是512个元素</strong>。好，<strong>当使用者要new一个AirPlane的时候，分配内存的那一件事情就落到这里来了，被我们控制了</strong>。
这里做什么事？首先检检查这个大小符不符合<strong>AirPlane</strong></p> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>size<span class="token operator">!=</span><span class="token keyword">sizeof</span><span class="token punctuation">(</span>AirPlane<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h3 id="『继承导致的坑』"><a href="#『继承导致的坑』" class="header-anchor">#</a> 『继承导致的坑』</h3> <p>我这边有一段注解，怎么会有错误呢？不可能有错。这不是编译器传进来的吗？编译器就是存进这个的大小到这里，所以这里还去检查，何必呢？<strong>如果继承发生就会有问题</strong>，但这不是我们现在要讨论的主题，我们这个故事第一部、第二部到第三部到趋近标准库的分配器，这中间不会发生这个事情继承的事情，所以这边我们也就不讨论了。</p> <p><strong>好，那这个讲检查可以想象这个检查一定会正确。只要不要有继承发生啊，就一定正确。</strong>
一次下来里头所做的事情跟刚刚的版本一完全一样，分配一大块，然后做细切多大块。</p> <p>所以这整个的动作跟前面第一版本是完全一样的，只是写法一些小细节不同。而和第一版本最大的不同，最<strong>大的改善就是优点啊借用借用同一个东西的前四个字节当成指针来用</strong>，这个概念叫in，bed，the point的概念。
<strong>这是一个很好的想法，所以在所有的内存管理上面都用了这种技巧。</strong></p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073522796.png" alt="image-20210722073522796"></p> <p><strong>这里头所做的事情分第一版本，我们现在是第二版嘛，跟第一版本完全一样啊。收到回来的指针放入单向链表</strong>的头，这样就回收了。
你可能会很开始有联想啊，我们回到上个月来，这里是五百一十二个元素，所以如<strong>果我是一个客户，我使用airplane，我用了一万次，将会是什么情况？你可以想象将会是五百一十二个，用完了之后再一次。</strong></p> <p>如果我接下去继续又要叫new，他又从这一万个里面去拿啊拿了五千个，又还了三千个啊等等等，所以这一条链表会有一个峰值高峰起好像是那个交通的高峰监控室。
测验啊，你曾经一次性要过最最高的累计总量，最后如果都还掉的话，就全部落到了这个链表里头。
他会不会还给操作系统？
当初适用这个方式来拿的，这个其实就是没有了。
那还的时候就应该调用free了。
这里都没有要用福利。这里只是把区块一个一个的回收到单向链表。</p> <h3 id="『注意事项』"><a href="#『注意事项』" class="header-anchor">#</a> 『注意事项』</h3> <p>来，这里我们看看上一个版本，上一个版本的这个函数也是没有free，他只是把区块回收到自由链表来。
<strong>那我们要检讨一下，这样子好吗？这一万个元素，也许是一百万个或者一千万个元素都不还给操作系统，这样好吗？</strong> <strong>这样当然不好当然不好，但是如果要还的话，技术难点非常高，这件事情我们后面再讨论。</strong></p> <p>回到这个简非常简单的设计，他**虽然没有还给操作系统，但是你也不能说它是内存泄漏，没有任何一个泄漏都在他的手上都在他手上。**好，看看执行结果。这个是测试啊，我先打印出现在这个AirPlane多大呀？</p> <p>测试重点在这里，我要输出前十个指针，看看他们的间隔。
反正这个测试的这个概念跟刚刚第一版本是完全一样，测试出来的结果间隔八，每一个区块就是把呃每一个区块就是八，所以它是紧紧相连。没有好用耗掉掉内存不是没有。我用掉cookie。非常好。这是左边的情况，右边的右边是没有写这一个operation new，on，operation。</p> <p><strong>左边当然是很好的，右边是原始情况</strong>，左边是改善的情况。怎么改善呢？<strong>因为我们写了一个小型的内存池，一个小型的分配器。</strong>
这是我们的第二版本。那就比第一版本进化了，就加上了内嵌指针，这样就非常好了。非常非常好。</p> <p>只除了最后我们有一个小小的遗憾，就是这个峰值最后全部累积起来了。他如果能够在想办法再还给操作系统，那就更好了。这是我们的第二版本。</p> <h2 id="⏳14-static-allocator"><a href="#⏳14-static-allocator" class="header-anchor">#</a> ⏳14.<code>Static allocator</code></h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073645367.png" alt="image-20210722073645367"></p> <p>第二个版本的分配器。相当不错。按照这个方式的进行下去。<strong>任何一个需要这种良好的内存分配的class，我们都为他写一个像刚刚那样的一个版本</strong>，也就是刚刚的那一个版本。
<strong>可是如果这样的话。这是一个从重复性的动作太多了，我们写代码的重复动作太多。</strong></p> <p>class a 你也写一套，这样b c d e 都写一套这样。从软件工程的角度来看并不合适。同样的东西我们不是可以把它集中到一个地方去吗？这样万一将来要改变的话，也比较方便改一个地方就好了。</p> <p><strong>那我们现在的版本三就循着这条路线。</strong> <strong>想要把刚刚的那些动作及抽出来集中在一个全局的函数呢，还是某一个类的里头，我会在class 里头。我们不喜欢全局的东西，在面向对象领域。所以我们最终决定了。把刚刚的那些动作抽取出来。放到一个class 里头。这个class 我们现在把它加allocatorr。哇，哦这个名字出现了。</strong>
大家一步一步接近标准库的那个分配器的做法。
这个allocatorr 里面就重载的这两个函数。
啊，不是。我就这一次就不再重载什么函数了啊就。
<strong>设计两个现在被业界大家公认叫的名字，一个叫allocate，一个叫dal kid。</strong></p> <p>我设为5，，一次要一大块，我这个一大块呢我有点夸张了，其实是不是太大的一块。我每次只要。
<strong>我要做五做什么用，我等一下观察的时候比较容易观察。在现实中呢呃，他可能是多少，这个就是这个团队的经验。</strong> <strong>也许这个团队认为你设计这个的团队认为嗯二十四个是不错的，大小太大也不好，太小也不好</strong>。</p> <h3 id="『标准库设计』"><a href="#『标准库设计』" class="header-anchor">#</a> 『标准库设计』</h3> <ul><li>标准库里面是多大呢？20</li></ul> <p>我们到了第二讲。被谈到标准库的做法，他是二期。</p> <p>我这个设计就比刚刚的第二版本简化多了。我们再看一次，刚刚第二版本。他这边又有representation，这里又有union啊，大家对union又可能不是那么熟悉。我把它全部简化。变成现在，你看这样。这个其实就是大家在学校里面写一个。
单向链表的时候会做的事情。画成图就更容易理解。
就是，如果我向。allocator 的要求这么大的话。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073715039.png" alt="image-20210722073715039"></p> <p>好，先摆着。<strong>设计好这样之后。其他的class 真正需要那种管理的class 服务啦，或者是Fool或者是Gool等。当需要用到这一种内存管理池，他只要写出这2个函数。而这两个函数里头刚刚是做了很多的动作。在</strong>这里写出来，现在不必了。
这两个动作就分别交给这个去做。这个就是上一页出现的allocator</p> <h3 id="『设计手法不错』"><a href="#『设计手法不错』" class="header-anchor">#</a> 『设计手法不错』</h3> <p>怎么做，先不必急，反正交给他去做。<strong>而这一个allocate 是专门为这个付来服务的，所以他是把它设计为一个静态的东西。这个allocate 你可以想象里面就是有一根指针指向一条链表。专门为他来服务。所以这是一个静态的</strong>。
另外这边右边的Goo呢也有一个。也是static，这边应该用红色的。叫左右可以对对应。<strong>意思是每一个class 里头都有专门为自己服务的小型的al locator，这个里面就有一条单向链表。</strong>
链表里面所挂的每一个区块就Foo这种大小，右边就是Goo这种大小。这样就是我所谓的把内存的事情抽出来放到二楼kate 里面，这样设计Fool的人不必再去管内存管理的那些。琐碎的事全部交给二楼kate 去做就好了。
由于这个是一个静态的，所以要在class 的外头去定义它。右边也是一样。</p> <h3 id="『这个我们叫版本3吧，就不叫per-class版本了』"><a href="#『这个我们叫版本3吧，就不叫per-class版本了』" class="header-anchor">#</a> 『这个我们叫版本3吧，就不叫per-class版本了』</h3> <p>好，这个比先前的设计干净多了。
application classes 也就是负或者是故。不再需要与内存分配的细节纠缠不清。所有的细节都让a lock 的去操心就好了。
这个就是我们的。
第三版本。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073740973.png" alt="image-20210722073740973"></p> <p>我观察什么事情？首先我要确认。我写的这个版本是对的，那第三版本的嘛。
所以我就我我打印出来看看它里面的值是不是我射进去的值，这个运作正确，没有宕机，没有crash 掉。
这是第一件。确保正确性。</p> <p>第二件。我又可以在这个输出里面看到一些我预期中的东西。
我预期什么呢？往前看这个allocator我的设计每次要的一大块其实是五个小块。所以每次要的那五个元素。
一定是相邻。他和另外的那五个不一定相邻。我希望能看到这个结果。
回到之前这个画面，果然我这个用黄色的线去去隔出来，每五个为五个啊，我们来看看。
这是负。
他的这五个最有射出直。
除此就是i 所以是一个流水号码。
这个大小是八，所以他的间隔是这是九零九八a 零a 八b 零。
就是这个间隔。
但是这个捂个汗这五个。
这从b 零跳到四零。</p> <p>fb 零跳到第一次啊**，这跳很远了，反正这是另外的五块。**
那从这个贴到这里呢也不一样，这个五d 六零跳到六零八零。
<strong>这都是不连续的了。</strong></p> <p>同样的讨论在左手边。
也是五个，按下面的五个按更下面的五个都是分离的。
这就是我们的第三版本。把内存分配的动作不要在散落于杂乱的。
在各个class 都写一份出来，不要这样，我们把它集中到一个所谓的nl cater 去这个ak 里面维护。
一条链表。
但是这个allocator的是专属于某个class 的，所以class A 有他自己的一条链表，class B有自己的一条链目标。
这就是我们的版本3</p> <h2 id="⏳15-macro-for-static-allocator"><a href="#⏳15-macro-for-static-allocator" class="header-anchor">#</a> ⏳15.<code>Macro for static</code> allocator</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073813902.png" alt="image-20210722073813902"></p> <p><strong>版本三的形式让我们看到了一个可以偷懒的地方。</strong>
呃，懒惰为人类进步的原动力，好像可以开玩笑的这么讲啊，我们为了让人类更舒服一些，所以不断的发明各式各样的东西。</p> <p>在这个版本三里头。我们对于任何一个class a b c d e，任何一个class。我们想要他有良好的内存管理的话。
我们就写出<strong>浅黄色的这一块，这三个地方。</strong>
这个写法非常的自私。class a 也是这么写，b，c，d 都是这么写。
这其中class a b c d 的名称有关系的，有吗？我们仔细看这个。没有任何关系。这命名就命这一个名称。ok 啊到了class 第一也令这个名称也ok。下面只有四行呢。没有任何悍妇相关的名字。
这一行，这个地方，<strong>名字相关。所以我们有没有可能把这些东西写成一个macro。</strong></p> <h3 id="『宏用来偷懒』"><a href="#『宏用来偷懒』" class="header-anchor">#</a> 『宏用来偷懒』</h3> <p>这个标题叫maccro for for static，static lock 就是刚刚的版本三。
我们现在要写maccro，<strong>有人很不喜欢maccro，我还不讨厌！！我觉得挺好的。啊，这一个转换成这样，左手边浅黄色的部分转成右边浅蓝色的部分。</strong>
这个是两个maccro，一个叫the clear。一个叫improvement。
这我我取的名字了。右边这个由于这一块是在class 的外头，class the 外头，所以单独为他写一个mako。其他的这两个是在class 的里头，所以这两个可以合并起来，写成一个micro。所以设计好这个mako 之后，这个里头的细节就让各位停格下来。慢慢的品位了。
设计好这个maccro之后。将来的任何的应用端的class。我们写应用程序的人要发展出我们自己的class。我们只要在claus 的里头。写这个maccro ，class，the 外头也写，也用这个mico。
<strong>你看这个里头用一个外头用一个。只要写这两行。就相当于写出了，左上角。浅黄色的这一段</strong>这两行mico 就相当于写出了这一堆有颜色的这一堆。
刚刚有检讨过，只有外头的这一个是汉类的名称相关。
所以外头的这一个要加上类的名称。
这样展开来才会是对的东西。
这个名称呀。这<strong>个就是。我所谓的版本四。</strong> <strong>一个很小的改善。这个改善呢其实技术上没有什么改善空间，这个改善只是让使用者能够更偷懒一点。</strong>
只要写出这两个maccro就好了。</p> <ul><li>有人这么极端吗？真的发展成这样吗？有，而且很有名。MFC，microsoft foundation classes. 这个是在有一段时间是叱咤风云的，这个全球都在用的一套library。</li></ul> <p>它里头就有这个东西。
啊，整个MFC之一的是让运用maccro，运用的非常的极致。当然vm fc 里面有这个东西，知道的人可能不多，直到这一些vn mx c 里面的宏的大部分的人知道的是另外的人。另外的几组非常有名的。这个不是那么有名。
好，这就是我们的第四版本。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073845963.png" alt="image-20210722073845963"></p> <p>这个是测试结果。
我既然把版本三右肝改成了版本四，我也要测试一下。
各位手上的代码都有这些东西。
测试结果在右手边。
<strong>那这是换汤不换药了，这个哈哈版本三是完全相同的，所以执行出来的这个我要探讨的部分也是完全一样。</strong></p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722073920020.png" alt="image-20210722073920020"></p> <p>所以版本1,2，3,4版本一是最一般的版本二呢加上了invited point inter。
版本三呢？把内存的动作抽取到丹妮的class 叫做a low heater 里面来。版本四呢在跟懒惰一点设计一个mico出来。
这里的一二三四兼进行到版本三，<strong>技术上已经完备了</strong>。</p> <ul><li>标准库的allocator 长这个样子。他就是刚刚我们所讲的版本三。只不过版本三里头有一根链表，</li></ul> <p><strong>而标准库的allocator</strong> <strong>要是会有很多的很多个allocator，其中有一个，很棒的，他长这样，他有十六根自由链表。</strong></p> <ul><li>也就是说他可以应付十六种不一样的大小。</li></ul> <h3 id="『标准库的自由链表针对所有的class来服务』"><a href="#『标准库的自由链表针对所有的class来服务』" class="header-anchor">#</a> 『标准库的自由链表针对所有的class来服务』</h3> <p><strong>所以他一定是一个全局的</strong>。他不是针对哪一个class 来。我们到了版本三的时候，我们是<code>per-class allocator</code> 的。
<strong>一个allocator针对一个类来服务，但这个不是。他针对所有的class 来服务。</strong></p> <p>这就是我们的第二讲的重头戏，标准库的allocator，，那我们现在已经掌握了原来技术的演进是这样的进化。
所以到了第1讲，马上就要结束了，再进入第2讲之前我们还有一些。C++基本构建的小东西。那这个地方我们要把补起来。</p> <h2 id="⏳16-new-handler"><a href="#⏳16-new-handler" class="header-anchor">#</a> ⏳16.New Handler</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074010460.png" alt="image-20210722074010460"></p> <ul><li>侯捷</li></ul> <p>现在我要补充两个。
很小的东西。
第一个叫new handler。
前面我们已经提过了这个。
这个名称new handler 啊，我们来看一下这边的叙述。是当of wait new。没有能力为你分配出。
你所申请的memory。
他会抛出一个异常呃这个名字。
有一些比较老的版本呢，而不是抛出异常，是return 零。
所以我们会养成习惯。
呃，也应该要养成这个习惯，你分配内存之后，你总是要检查一下那个指针是不是零。
呃，确认啊你后面的运用是对的。
所以现在这个有新旧版本。
失败的时候，有的会抛出异常，有的是return 零。
不过这边说你也可以让编译器一定。
retaining, 而不是抛出异常。
那就这么做new 的时候指明no throw。
他也可以。
啊，我我我也知道啊，我也可以想象。
我们一般应用程序已经不太在乎什么，你是抛出异常，你还是re 振铃，还是强制要他瑞泰龄，而不抛出异常。
啊。
很多红有世上根本不检查这个成不成功，他认为。
内存呢？
反正多的要命，我大概不会走到山穷水尽那一天都不去检查，这个不是一个好现象。
另外也有一大堆一大部分的程序员是。
对于异常根本不了解，所以对他这边抛出异常了，也不知道怎么处理。
好，一场是另外一个话题了，我有另外一门课程，他异常好，这里不管了。
重要的是，现在要补充的重要的事情是。
c 加加平台会在抛出异常之前，就这个异常，该等额。ok 这个异常之前呢抛出去就不可回收了啊这个。
覆水难收了，抛出去之前，它会先调用某一个函数，而且是不止一次的调用。
什么函数呢？由你设定的函数，你通过这一个方式把它射进去。
你的函数要长什么样子呢？长这种样子。
它是一个。
返回值是boy。
参数呢没有参数，只要这种形式就可以。
所以这边有一个type define 啊，紫色的这个就是这种形式。你只要写出一个像紫色这样的一种函数出来，你就可以调用。
that new handler 把它塞进去。
设好了之后就不必管了。
然后只要抛出异常之前，都一定会调用你的这个函数。
所以c 加加平台这样的设计是为了给你一个机会。
因为一旦内存不足，整个软件也。
也不能运作了。
所以他借这个机会来通知你。
也就是调用你的这个函数，有你来决定该怎么办。
并且他会一再的通知。
这个事情我们前面看过。
很非常全面，之前我就已经给各位看的，在vc 底下。
a person new 的源代码，这里面就有一个while loop 不断的在调用没了。
所以当。
不管什么形式，用new 的形式，用operate a new 的形式。反正最终会跑到这里来。
一旦这个失败。
在这边的说法就是要。
你这边的说法就是要抛出异常喽。
但是被调用一次你的这个函数。
再用完了之后。
这边。
这个动作叫霍尼韦尔h vc 底下架靠定位曲。
顾名思义呢就是调用new kindler。
要用完了以后回来再分配一次。
所以他的意思就是。
他让你去看看你有没有什么补救措施。
然后他再调用一次，说不定这一次就成功了。
所以一个new handler 该做什么事情呢？
我看过一些书籍，里面会谈到五样事情，但我认为。
真正有用的只有两件事情。
第一件事情就是让更多的内存可用。
既然会调用到你这个函数来，就表示已经山穷水尽，没有那种可用了。所以你怎么样让更多的内存可用呢？
现在也就是零了。
或者是极小值了。
怎么样可用，你就赶快去检查一下手边的内存的消耗量，看看哪一些可以先释放掉。
不影响整个运作，你就先去释放。
释放完了之后，这后面微曲id lme 你释放完了之后，他会再分配一次，看这一次会不会成功。
这就是c 加加new handler 这个平台的设计。
没有人能够教你new handler 里头该做什么事。
只会教你这个new 很多的形式长什么样，子长这个样子。
进去之后呢，第一件事情有意义的就是这一个。
再要不就是a aboard，就你也没办法。
放弃吧。
a about 放弃或者the exit。就是强迫让程序结束。但是也许在结束之前，你要你要丢出一个信息告诉使用者。
等等等。
就有那么一个机会。
我们来看看怎么我举一个例子，写一个new handler。
这个就是我的牛汉德。
他必须return voy，没有参数值，这样就可以了。
我在这里头呢，我就先抛出一个。
先丢出一个信息。all of memory of all.
这就符合我在上一页这两个做法中的第二个。
好，设计好这一个new heater 了之后，在面里头我去调用它。
要用这个函数把它塞进去。
你看到上一页这一个设计这个that new handler c 加加标准库提供的。
你存进去给他，他会传递一个相等的东西给你。
相等地位的东西。
这个设计是这样，也许你先前已经放了一个new header。the new handle a.
你现在要放new handle the b 让你滴放进去的时候，a 会返回来给你。
你可以登记起来。
这个设计是这个原因。
为了这个目的。
好，回到这边来，所以我就把它射射好了之后。
我就动态的去分配内存，分配很多，这样够多了吧。
这要是不够多，那就在再做三个零。
这样去试试看。
看你舍的这一模式的这一个有很多。
会不会？
被调用。
这个that the new handler。我刚刚说是c 佳佳提供的一个函数，它的源代码在vc 底下是长这样。
但这已经不是我们关注的重点了。
只是让你看一看他是这样子去设。
这个执行结果。
在这边。
这是我手头上的后来比较新的版本，用的木c 四点九去做的版本。
那么早期我曾经用玻璃c 四点零做过，确实会输出out of memory。
但后来在右手边这个版本呢，却也没有输出。熬of memory。
所以。
这个这一部分可能在不同的平台上呢，他是怎么行为，你要测试一下。
在你自己手上的平台呢测一下。
好，注意这段话。
这个例子里头的new handler 如果没有调用bot 的这个动作，没有调用它的话。
那就不会离开程序。
因此。
上一页谈的这个动作就会不断的进行。
不断不断的进行。
这是右手边这句话。
好，这个是new handler 啊，我们知道它的作用，也知道怎么设定，它也知道他的形式。
下面我要谈的是这个。
is this get it before?
这个是c 加加二点零新增加的两个关键字。
说他是关键字好了。
它的应用像这样。
可以在class 里头。
这些函数指定它是default 还是is it？
顾名思义，比例的就是这个函数不不要。
seaport t 就是这个函数，我要用默认的版本。
我不要这个函数，这个很容易理解，但这个函数的默认版本是什么，这个就有点匪夷所思。
事实上是，如果要设低bot 的话。
那就表示那个函数有默认版本了，什么样的函数才有默认版本呢？
在c 一家家里头只有。
拷贝构造函数。
拷贝赋值函数。
吸构函数。
他们有默认版本，也就是说如果你没有写的话，编译器会给你一套所谓的编译器合成法。
这个事情就我们在这里不提啊。什么叫编译器合成板，你都做什么事，现在就不讲了。会议有那么一个版本，所以这个default 指的是那个版本。
好，二点零的关键字，我们看这一句话。
这句话说。
这两个关键字不只是适用于刚刚我所说的。
拷贝构造拷贝赋值，还有吸构函数，不只是这样啊，还可以适用于operation new 根a renew。
还有。did it are already it.
有这么一句话。
我就想那我来试验看看，因为我确实想不通。
operation new operate delete. 他怎么会有b for t 版本，那到底是什么？
于是我写的这个程序。
妇。
先认识一下这个就是。
operate the new and delete.
这个是already 利用话delete。
我让三我随便我随便这四个里面，我随便放，我随便选两个，我选的上面这两个让他等于逼迫。
就刚刚我说了，我不清楚是他什么是他的逼迫，所以我想试试看。
编译结果出错。
说。
cannot be it for you.
就他们两个不可以default。
这个就符合我们对技术的理解啊，不可以这样。好，这打叉。
他delete，我说我不要这两个。
好，ok 这样子写好，这是可以通过的。写好之后呢，我来测试一下。
妇。
不。
这里有四个动作。
其中呢在这里吃个动作的三跟四。
三焊四。
调用的。
是谁？
三三和四调用的就是这两个。
左右比对一下。
这两个已经在设计的时候说，比例的是不允许有了。
所以这两行编译失败。
而上面这两个动作呢？
他调用的是左手边的这两个。
这两个。
如果写成逼迫的是不可以，所以我已经在。
艾玛里面把它变成注解了。
你可以拿到这张代码，你会看到我把它变成注解，就不存在这里。
所以。
不存在这两行，所以他们是可以被调用到的。
可以通过。
我要试着另外一种情况。
上面是不下面是故。
我这次选的是。
这两个做我的目标把它给力去掉。
反正我就是在这几个函数里头呢，任意的测试啊。default 或on this，it 看看这个执行结果。
就这两个因为被delete 掉了。
所以固。
the new 跟delete 都不可以实行，不可以成功。
他说俄锐是可以的。
因为我这里面并没有去对array 令汉already delete。做任何事情。
这是对于二点零的两个新的关键字。既然说他们焊六delity 有点关系，所以我就。
做了这些测试。
这个就是我们整个第一讲的内容啊，c 加加的primitives 这些基本构建的。
啊，弄的非常的。
彻底并且也已经发展出一个小型的。
针对每个class 自己的一个小型的分配器。
很快的，我们要进入第二讲，就会谈到标准库这个大型的分配器的做法。</p> <ul><li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074039409.png" alt="image-20210722074039409"></p> <ul><li><p>侯捷</p></li> <li><p>侯捷</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074106279.png" alt="image-20210722074106279"></p> <ul><li>侯捷</li> <li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074135743.png" alt="image-20210722074135743"></p> <h2 id="✅第2讲std-allocator⭐️"><a href="#✅第2讲std-allocator⭐️" class="header-anchor">#</a> ✅第2讲<code>std::allocator</code>⭐️</h2> <h2 id="⏳17-vc6-malloc"><a href="#⏳17-vc6-malloc" class="header-anchor">#</a> ⏳17.VC6 <code>malloc()</code></h2> <p>各位，现在我们进行内存管理的第2讲，在第1讲之中呢，我们已经呃彻底的了解了c++给我们的各式各样的工具，我们叫语言的构件，construction
那么从现在开始呢，我们要来建立一个<strong>内存管理的管理器</strong>，或者我们叫做<strong>分配器</strong>，自己来模拟，自己来想象、来开发。中间经过很多的过程，倒不如我们就拿一个很棒的东西来学习。所以在这第2讲里头。
我要拿标准库的Acer，看看他是怎么做的。</p> <p>在这个第二讲里头，不但我们我要带大家去看看这一套东西的运作方式，我还会带大家来看看它的源代码。这是非常宝贵的部分，被我精简了，所以整个范围、整个这个分量也不是太重，不到三百行。
呃呃这是一个很很很宝贵的一个一份资源。</p> <ul><li>西北有高楼，上升浮云及</li></ul> <p>在准备这个讲这一讲的时候，我突然想到这两句画这个是古诗十九首里头的一首的开开天两句话，西北有高楼上吴云奇。我就想到我们现在要学习的这个东西呢。
就是一座高楼。呃标准库的分配器称得上是一座高楼吧？
是一座值得我们去学习的东西，去认识的东西。</p> <p>西北有高楼，这个我想到一件有趣的事情，在网络上看到一段易事，西方有一位学者就问中国的学者说为什么孔雀东南飞？这个学者就说啊因为西北有高楼，这个对应到孔雀东南飞。这个在这一段对话里面的西方学者是谁，中国学者是谁呢我都忘了，我对人民呢不太容记忆力比较差一些。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074335976.png" alt="image-20210722074335976"></p> <p>先回想一下，在第1讲里面，<strong>我们其实已经自己开发的一些小型的分配器</strong>，这些分配器是放在某每一个class里头，叫<code>Per-class allocater</code>这里面的设计其实已经达到了很不错的水准，还记得吗？</p> <p>我们有版本一，有版本二，那个版本二呢里面用到了in bed points的概念的做法，<strong>嵌入式指针，所以绝对没有浪费任何一个字节</strong>借用obejexr本身前面四个字节拿来当作指针的这个做法。</p> <p>所以到了版本二，这版本三是那个<code>Macro</code>把它转成<code>Macro</code>，所以这个版本我们我们就谈版本二，所以。</p> <p>这个过程里头呢在这个设计里头呢，其实已经是达到了内存管理的要求了!!**也就是尽量减少对malloc的调用，因为据说malloc很慢。**不过到了第三讲我们现在是第二讲，到了第3讲我们会看到，<strong>其实malloc不慢啊，这个，大家对它是一个误解。</strong></p> <p>好，现在先拿回来。据说malloc很慢，所以我们想要降低，那已经达到这个要求了！！因为那条链表嘛，一次挖一大块，自己去切小块。但还好现在达到了。</p> <p>但<strong>还有一件事情还没有达到</strong>，就是malloc得到的区块其实是带着cookie的。这个cookie的我们叫<code>overhead</code>的一个额外的开销，这个开销，我们其实关注的是它的这个耗用率啊、占用的比率。</p> <p>如果你的区块本身很大、非常大，也不要说很大非常大了，就是比如说100哈。
那么cookie呢？<strong>cookie我们知道</strong>是，<strong>一定是占用8个字节</strong>，我们现在以VC来讲，所以这个比例算下来<code>8%</code>，这个就算是他的浪费率，必要的浪费。</p> <ul><li>那如果你的<strong>区块比较小，你的浪费率就高</strong>，因为cookie是一定占用八个字节。</li></ul> <p>所以在现在，一般现实运用之中呢，其实对象object本身都不会太大！在我们现实在<strong>工业等级</strong>的啊，我们在做通常都不会太大，<strong>但是量很多</strong>，<strong>我们叫做海量的小区块。<strong>这种情况之下呢，cookie的浪费就让我们觉得不太能忍受，特别尤其是我们在工业级的东西，海量的小区块、内存块，而</strong>这些内存块又是一样的大小</strong>，cookie主要是记录区块有多大，但你现在的所有的cookie是一样的大小，或者只是某几种啊三百万个里面只是分为两三种大小而已，那<strong>似乎没有必要去cookie</strong>，去需要这个cookie。？？？？</p> <p><strong>所以有没有办法把第1讲的那一个那个那个设计把它做的更好一些</strong>，能够去除这个cookie，<strong>啊这就是我们要奋斗的目标</strong>，</p> <p>内存管理：</p> <p>一个就是效率要提高</p> <p>一个就是空间率要精简！！</p> <p>啊<strong>我们现在希望能够同时达到这两个诉求</strong>。
呃这1页在第1讲里面也曾经出现过，在某一个范围某某某一张投影片里头出现过，呃当时我说后头还会越讲越清楚！！</p> <ul><li>到了第3讲了，<code>malloc</code>就是非常清楚的讨论这一块。</li></ul> <p>那现在这边呢，还是让大家再理解一次啊，<strong>cookie的计算方式</strong>：
1、这个是你要的大小，我没有按照比例画没有按照比例。这个现在是C，我是十六进位的C。C那就是12，10进制的12。好，当你要十二个字节这么大的时候，<code>malloc</code>给你的是多少呢？这是VC6.0，底下，其实是上面带着一包浅色的。下面还有一个也是浅色的。
我们现在都不要去分析他做什么用，<strong>总之他就会这样给你</strong>。
2、然后呢上下cookie，然后再加上，看看加起来以后是不是16的倍数。不是的话把它调到16的倍数，所以这边有个填补物，pad，所以填补多少这个不一定！！</p> <p>3、现在我们按这个例子来说说看，这个是C，加上上面是32，这我这一格是4个字节，下面还有一格，再加4，加完之后，上下cookie（四乘以二），加起来是我这个是十六进位。</p> <p>我十六进位加法还蛮快的，反正你自己加起来是38Hex
38还要调到16的边界呢，你看这边必须是室友的备注，所以是40Hex
那因此这个从38到40要填18个字节，那就是这个浅绿色的部分！</p> <p>这样子算出来之后，当你<code>malloc</code>要12个字节的时候，其实你要的是这一大块，<code>malloc</code>给你的是这么一大块，<strong>而你得到的指针指向这里</strong>，所以你会往下写写东西。好，所以这么一大块消耗掉这么一大块是多少呢？40H ，就被登记在这个cookie里头，这一整包就给你了！！你就拿到了这个指针了，当你不需要的时候，你还，要用free，malloc对应的是free，free你就还这一根指针！</p> <blockquote><p>难点：不知道机制？？</p></blockquote> <p>然后<strong>free这个函数呢它有一些机制</strong>，它自然会调整，去看到这个cookie就知道：他要回收的是这一整块40H</p> <p>好，这个就是VC6.0下malloc的一个给你消耗的东西，而我们现在希望去除，好，我们看看怎么做。再往下：</p> <h2 id="⏳18-vc6标准分配器之实现"><a href="#⏳18-vc6标准分配器之实现" class="header-anchor">#</a> ⏳18.VC6<code>标准分配器</code>之实现</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074422838.png" alt="image-20210722074422838"></p> <ul><li>不<strong>同的编译器</strong>所附带的标准库里头的<strong>分配器做法</strong>可能都不一样。</li></ul> <p>所以我现在准备了『『三种主流编译器』』里头的，所带的这个分配器，我们看看它有什么作为。</p> <p>第一个vc。我这个是比较早期的版本VC6.0，那么现在新的版本呢，这个你也可以翻翻翻开你手上了，手上的VS2013、VS2015，你都可以找到源代码来比较一下，看他有没有长进。我这边不再继续看新的VS2013或VS2015。</p> <p><strong>是因为后面我们要学习的对象，不是拿这个来学习！</strong>！！</p> <p>是拿GNUC，那个号称是非常棒的一个，可以说最棒的一个矢作实现。</p> <p>他说我们现在还是来看一下VC6.0，他的<code>allocator</code>，在这边的定义在这里。
<code>allocator</code> 最重要的两个函数在这里。</p> <p>好，我们进去看看他做什么事情。<code>allocate</code>所做的事情，我这个线条都把你拉好了。他调用这个函数。这个函数里面做的事情就是<code>operator new</code>好，我们已经知道<code>operator new</code>是什么啦。我们在第1讲里面已经非常清楚他了，他的背后就是<code>malloc</code></p> <blockquote><p>VC6.0的大跌眼镜。</p></blockquote> <p>所以，vc 的这个<code>allocator</code>里头，他根本没有做任何的内存管理。他只是把<code>mallo</code>换一个样貌。换成什么样帽，换成这一个函数呈现出来——<code>allocate</code></p> <p>他的兄弟<code>deallovcate</code>呢？里头做的动作是<code>operator delete</code>
我们在第1讲也学过了，这个是什么？他的里头就是调用free。
所以这个<code>allocate</code>,什么精巧的动作都没做。</p> <p>那这个allocate 在vc 的容器里头。所有的容器，我没有全部列出来，但是这些都是最经典的，最有代表性的。这些容器的第2个模板参数，默认值都是他！！
这样我们就知道了，原来在vc 底下，你使用容器。最终的元素这个分配都是靠着<code>malloc</code>取得的。<code>malloc</code>都带着<code>malloc</code>给你的内存块都带着cookie。好，我们现在有这个观念。
这里的分配，是以你指定的这个元素类型为单位。
所以如果指定512，意思是要分配512个整数。
如果这边指定的是，double， 那就是要分配512个<code>double</code></p> <blockquote><p>注意事项。</p></blockquote> <p><strong>它是以元素为单位。我现在特别强调这一点，是因为:后面我们要学习的那一个,很棒的那一个，他不是这样，他是以字节为单位。</strong></p> <h2 id="⏳19-bc5标准分配器之实现"><a href="#⏳19-bc5标准分配器之实现" class="header-anchor">#</a> ⏳19.BC5<code>标准分配器</code>之实现</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074459960.png" alt="image-20210722074459960"></p> <p>也曾经叱咤风云的BC++这个编译器。他所附带的<code>allocator</code> 设计在这里。
他的两个重要的函数在这边,这两个函数所做的事情，在这里，原来他们里头就要用这个。<code>operator new</code>和<code>operator delete</code> 。</p> <p>第一讲里面你已经非常清楚了。他说什么事情？这个就调用<code>malloc</code>，这个就是这样。
所以在BC底下，原来分配器也是什么都没有做。他就是让<code>malloc</code>一来。</p> <p>这个是在BC底下的容器。容器里面的第2个模板参数都指定要用这一个<code>allocator</code> 的。</p> <p><strong>所以这个情况跟刚刚看到vc 完全一样啊</strong>，</p> <p>我们也也了解了，在这个平台下面。你如果有100万个元素在容器里头，我们现在非常强调容器呀，因为现在写代码。你都不需要再自己开发设数据结构了，那些数据结构最经典的都已经写成容器了！！</p> <p>那标准库里头，所以我们很重视容器的效率，然后现在发现呢，容器用的这一些allocate 这些分配器，他其实只是每一块都带着cookie</p> <ul><li>那我们现在的目的是希望能够去除这个。<strong>去除cookie 有一个先决条件</strong>，就是你的区块要一样大小。如果你的区块是有大有小有大有小，你怎么可以去除cookie呢？<strong>cookie 就是在记录区块的大小，那你不能去除它</strong>。</li> <li>『『但是现在容器里头的所有的元素是一样的大小，这先决条件这个很重要。』』</li></ul> <blockquote><p>重点知识！！</p></blockquote> <h2 id="⏳20-g2-9标准分配器之实现"><a href="#⏳20-g2-9标准分配器之实现" class="header-anchor">#</a> ⏳20.G2.9<code>标准分配器</code>之实现</h2> <h3 id="『你以为仅仅这样？』"><a href="#『你以为仅仅这样？』" class="header-anchor">#</a> 『你以为仅仅这样？』</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074531906.png" alt="image-20210722074531906"></p> <p>接下来看看，号称非常棒的一个GNUC，底下的，它的标准库里头的分配器。
这个是他的class。两个重要的函数在这里。这两个重要函数里面做的事情。
这两个已经拉过来，他们所做的事情呢，我都已经把你拉好了。</p> <blockquote><p>最后发现：他的头其实跟前面VC和BC呢，是一样，都是调用这个。</p></blockquote> <p>这个的底底层就是malloc跟free，所以这边说。GNU2.9，我待会会带大家看很新的版本4.9，2.9版的allocator 也不过就是这样而已。VC和BC 刚刚你看的也是一样。<strong>那我们想学什么呢？看起来没有什么要学习的。</strong></p> <h3 id="『2333奇葩』"><a href="#『2333奇葩』" class="header-anchor">#</a> 『2333奇葩』</h3> <p>这边有一句话：
在他这一份头文件里头，这个源代码，头文件里头，他说：不要使用这一个头文件，这个方案！！他就说他自己使用的是一个不同的<code>alloctor</code>。说这个现在这个头文件，你看的这一个啊，看起来没什么作用的这一个呢。并没有被引入到任何的容器里头。这真是让我们吓一跳。</p> <p><strong>那到底这些容器用的是什么样的分配器呢？？这个是标准的呀！</strong>！我们继续往下。</p> <p>于是我们把这一个版本下面的容器通通找出来。看看他的第二个模板参数。原来他们用的真的不是刚刚那一个，是这个叫做<code>alloc</code>
这个东西这个也不知道怎么发音比较顺啊，所以我后面当我在讲话的时候，我也只好念<code>ALLOC</code>，这个不太好听。</p> <h3 id="『事实上是这样』"><a href="#『事实上是这样』" class="header-anchor">#</a> 『事实上是这样』</h3> <blockquote><p>不是用<code>alloactoe</code>，而是用<code>alloc</code>，</p></blockquote> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074606332.png" alt="image-20210722074606332"></p> <p>看起来，也许奥妙就在这里头，的确是！！<strong>所以我们待会儿要去看的就是这一个东西。那这个东西我这边先示范1次给你看</strong>。其实在第1讲一开始。我说要把各式各样可以分配内存的工具都能来用，其中就已经用过一次这个东西了。
呃，用法就是这样，或这样，当然这样子的写法马上给你一个感觉，</p> <p><strong>这个a l l o c 到底是什么东西呀？是一个class 还是一个object？这个地方既然写在这里，他当然是一个class。一个type 类型。</strong>
那已经知道他是类型了，而这边用写成这样。那么表示这个函数是这里头的一个静态函数才能够这样写，才能够这样调用。而这是静态函数啊，我们就这个概念呢。
以静态函数来实现这两个重要的角色。</p> <p>啊，这里呢当你给他命令的时候，512指的是512个字节。啊，因为后面我们会看到他并没有去接受，说你告诉他一个单元是什么，一个元素是什么，他没有接受这种东西。他的脑袋里面就只想到自己Byte。好，再一次注意这个标题。</p> <p>啊，不是用<code>alloactoe</code>，而是用<code>alloc</code>，<code>alloc</code>这个就是我们学习的对象喽。</p> <h2 id="⏳21-g2-9std-allocvs-g4-9-pull-alloc"><a href="#⏳21-g2-9std-allocvs-g4-9-pull-alloc" class="header-anchor">#</a> ⏳21.<code>G2.9std_alloc</code>VS <code>G4.9__pull_alloc</code></h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074636133.png" alt="image-20210722074636133"></p> <p>往下看。而今安在哉。
GNUC 二点九版。虽然呢我现在还没有带大家去看，但是我已经一再的告诉你，那是一个很棒的东西。那又何必去提2.9，难道现在我所2.9在飞向非常新的版本，难道他不在了吗？不然我何必去提二点九了。
他还在，不过！！
注意这个画面：
<strong>2.0的这个a l l o c 到了4.9，也许在4.5就开始了啊，我不知道。就换成了这个名字！！并且变成了一个编制外的东西</strong>。</p> <ul><li>也就是说。这个GNU后来发展到比较新的版本啊，这个好东西，变成了编制外的！！</li></ul> <p>其实刚刚这个2.9的这个<code>a l l o c</code> 也是编制外的，编制内的是什么？就是那个标准的叫<code>allocator</code>的那一个分配器。所以这个是编制之外，也编制外的东西，现在我就呈现它的源代码的一小部分给各位看。这个是GNU2.9版本，这个是4.9版。现</p> <p>在由于，我们还没有去看过源代码，所以你没有办法发出会心的一笑。！！
再过一个小时之后，你就笑得出来了。</p> <p>然后我们要看的是，我会带你看这一块，这是二点九，这比较好看。而4.9来跟这个只是换了一个风貌里，比如说变量的名称换了啊，比如说这你看这3个，这是变量名称在这边都存在，名字有一点点变化。
等等等，下一页也还有。我这个总共准备两页。让你比对一下，其实就是以前的那个东西，2.9的那个东西。所以这是一个好东西，现在仍然可以用啊，这样我们就很放心。
好，我们看看这个过程，这两页的过程里面有没有什么可以需要提的。</p> <p>oK，这个，这个就是在二点九班底下，容器可以指定这一个分配器来做支持。
到了四点九版，就如果你要用这一个特殊的东西——<code>pool_alloc</code>好东西的话，你就要写这样。所以你就可以感受他的名字换成这个了。而且这个东西又被特别包在这一个命名空间中。啊，你要把它全部写出来。我们后面会介绍一种比较方便的写法，则会用到C++11。</p> <p>你得问C++2.0的一个特性，一个语法特性就可以把这个写的很漂亮，觉得很精简。
啊，注意这句，C++呃，GNU四点九呢，有很多的extended （扩充的）</p> <p>所以我们在这个第五讲，现在是第2讲<strong>到了第5讲的时候还要讲到很多的分配器</strong>，就会把其这里面扩充了，再拿一些出来讲！！什么<code>bitmap_allocator</code> 啦。什么<code>marty marty thread allocate</code> 等等等。有很多啊，那么现在这个。<code>pool_allocate</code> 就是其中一个。好，所以这个而今安在哉呢，在我这边准备了两页，可以看一看。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074728586.png" alt="image-20210722074728586"></p> <h2 id="⏳22-g4-9pull-alloc用例"><a href="#⏳22-g4-9pull-alloc用例" class="header-anchor">#</a> ⏳22.G4.9<code>pull_alloc</code>用例</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074803986.png" alt="image-20210722074803986"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074828451.png" alt="image-20210722074828451"></p> <h2 id="⏳23-g2-9std-alloc"><a href="#⏳23-g2-9std-alloc" class="header-anchor">#</a> ⏳23.G2.9<code>std alloc</code></h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074910937.png" alt="image-20210722074910937"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722074942375.png" alt="image-20210722074942375"></p> <h2 id="⏳24-g2-9std-alloc运行一瞥01-05"><a href="#⏳24-g2-9std-alloc运行一瞥01-05" class="header-anchor">#</a> ⏳24.G2.9<code>std_alloc</code>运行一瞥01-05</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722075008313.png" alt="image-20210722075008313"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722075301368.png" alt="image-20210722075301368"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722075330541.png" alt="image-20210722075330541"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722075353882.png" alt="image-20210722075353882"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722075412008.png" alt="image-20210722075412008"></p> <h2 id="⏳25-g2-9std-alloc运行一瞥06-10"><a href="#⏳25-g2-9std-alloc运行一瞥06-10" class="header-anchor">#</a> ⏳25.G2.9std_alloc运行一瞥06-10</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722075455342.png" alt="image-20210722075455342"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091355500.png" alt="image-20210722091355500"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091413801.png" alt="image-20210722091413801"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091435529.png" alt="image-20210722091435529"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091452017.png" alt="image-20210722091452017"></p> <h2 id="⏳26-g2-9std-alloc运行一瞥11-13"><a href="#⏳26-g2-9std-alloc运行一瞥11-13" class="header-anchor">#</a> ⏳26.G2.9std_alloc运行一瞥11-13</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091523183.png" alt="image-20210722091523183"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091545845.png" alt="image-20210722091545845"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091607874.png" alt="image-20210722091607874"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091642942.png" alt="image-20210722091642942"></p> <h2 id="⏳27-g2-9std-alloc源码剖析（上）"><a href="#⏳27-g2-9std-alloc源码剖析（上）" class="header-anchor">#</a> ⏳27.G2.9std_alloc源码剖析（上）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091715183.png" alt="image-20210722091715183"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091733190.png" alt="image-20210722091733190"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091754602.png" alt="image-20210722091754602"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091814619.png" alt="image-20210722091814619"></p> <h2 id="⏳28-g2-9std-alloc源码剖析（中）"><a href="#⏳28-g2-9std-alloc源码剖析（中）" class="header-anchor">#</a> ⏳28.G2.9std_alloc源码剖析（中）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091845207.png" alt="image-20210722091845207"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091908558.png" alt="image-20210722091908558"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091926855.png" alt="image-20210722091926855"></p> <h2 id="⏳29-g2-9std-alloc源码剖析（下）"><a href="#⏳29-g2-9std-alloc源码剖析（下）" class="header-anchor">#</a> ⏳29.G2.9std_alloc源码剖析（下）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722091959771.png" alt="image-20210722091959771"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092018644.png" alt="image-20210722092018644"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092038113.png" alt="image-20210722092038113"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092053857.png" alt="image-20210722092053857"></p> <h2 id="⏳30-g2-9std-alloc观念大整理"><a href="#⏳30-g2-9std-alloc观念大整理" class="header-anchor">#</a> ⏳30.G2.9std_alloc观念大整理</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092128373.png" alt="image-20210722092053857"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092410959.png" alt="image-20210722092410959"></p> <h2 id="⏳31-g4-9pull-allocator运行观察"><a href="#⏳31-g4-9pull-allocator运行观察" class="header-anchor">#</a> ⏳31.G4.9pull allocator运行观察</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092436210.png" alt="image-20210722092436210"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092500838.png" alt="image-20210722092500838"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092532207.png" alt="image-20210722092532207"></p> <h2 id="✅第3讲-malloc和free底层⭐️"><a href="#✅第3讲-malloc和free底层⭐️" class="header-anchor">#</a> ✅第3讲-malloc和free底层⭐️</h2> <h2 id="⏳32-vc6和vc10的malloc比较"><a href="#⏳32-vc6和vc10的malloc比较" class="header-anchor">#</a> ⏳32.VC6和VC10的malloc比较</h2> <h3 id="_32-1-『补充资料』"><a href="#_32-1-『补充资料』" class="header-anchor">#</a> 32.1.『补充资料』</h3> <h3 id="_32-2-malloc本身不是系统调用是函数（招聘面试问）"><a href="#_32-2-malloc本身不是系统调用是函数（招聘面试问）" class="header-anchor">#</a> 32.2.malloc本身不是系统调用是函数（招聘面试问）</h3> <p>而是，2种实现方式，<strong>brk系统调用</strong>，在小于128K的内存申请的时候，会调用brk，会在内存的堆空间的edata这个游标下面申请。申请空间，mmap，它是在edata到栈的最小内存地址之间申请内存，</p> <p>当然brk和mmap申请的是 虚拟的内存空间啊，它并没有真正的申请到主存上的物理内存空间，想要真正拿到物理空间，还要在第一次访问的时候，会发现这个虚拟内存地址没有映射到物理内存地址，于是触发,一个叫做缺页中断。</p> <h3 id="_32-3-《stl源码剖析》摘录"><a href="#_32-3-《stl源码剖析》摘录" class="header-anchor">#</a> 32.3.《STL源码剖析》摘录</h3> <p><strong>P53-P54</strong></p> <p>SGI正是以malloc和free完成内存的配置和释放</p> <ul><li>考虑到小型区块所可能造成的内存破碎问题，<strong>SGI设计了双层级配置器</strong></li> <li>第1级配置器直接使用malloc和free</li> <li>第2级配置器则视情况采用不同的策略，
<ul><li>当配置区块&gt;128Bytes时，视之为“足够大”，便调用第1级配置器。</li> <li>当配置区块&lt;128Bytes时，视之为“过小，为了降低额外负担（overhead），便采用复制的memory pool（内存池）整理方式，而不再求助于第1级配置器。</li></ul></li></ul> <p>整个设计究竟只开放第1级配置器，或是同时开放第2级配置器，取决于<code>__USE_MALLOC</code>是否被定义。（我们可以轻易测试处理）</p> <ul><li>现在我们进行内存管理的第三讲，我要谈的是malloc跟free，这两个函数大家并不陌生，它是<code>C语言层次</code>的东西。
呃为什么要谈这个呢？我们在第二讲的时候谈到啊：一个标准库的分配器的设计。</li> <li>所以如<strong>果我们不能够了解malloc这个根源的它的效率如何的话，总是觉得拼图少了一块很重要的一块。</strong>
我们<strong>一般可能会有一个误解。会觉得malloc挺慢，所以我们也尽量少去要用它，也『『因此』』才在这个上头呢做了很多的内存管理。</strong></li> <li>那第三讲里面可以让大家可<strong>以非常清楚地了解到，到底他慢不慢，他快不快，除了快慢之外，他还有什么事情是我们要了解的？</strong></li></ul> <p>第三讲的内容我非常喜欢这一句话，胸中自有丘壑。我也<strong>很希望在这一讲里面带领大家去理解这个整个背后的机制，他的动作，从此以后，大家胸中自有丘壑啊。你非常清楚整个内存系统里面呢这个到底是怎么一回事</strong>。
呃但是<strong>谈到这个malloc，我会带大家去看源代码的『动作』，就不会再像上一讲那样子看一个完整的源代码，那个太太吓人了。</strong> <strong>malloc里头的设计太吓人了，太复杂了。呃所以我只会讲他的从源代码里面之后理解出来的它的运作模式，画很多的图来带领你。</strong>
当然一些很关键的源代码的动作，非常关键的、少量的我还是会把它显示出来。</p> <ul><li>那么这既然谈到这些动作它是根源于某一个源代码，我们就要谈一谈源代码的版本咯。 『VC6.0』</li></ul> <p>vc6.0呃这个源代码以及他的动作六点零，这个时间很很早了呀。呃好。<strong>待会儿我会解释啊，其实到了现在那个里头的动作都是差不多的</strong>，那我们选择一个版本，那其他的版本怎么办呢？
<strong>在vc底下它是这样的行为，在GNUC底下，在GC底下怎么办呢？我们没有精力，我们也没有必要一个一个去看它。</strong>
所以这个又是我很喜欢的一句话，触类旁通。</p> <p>我们已经懂了一个机制之后，而且我告诉你，我其实看过了其他的版本，但我们没有办法一个一个细讲，知道一个之后呢就能够触触类旁通去知道其他的行为模式，大概也差不太多了。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092625921.png" alt="image-20210722092625921"></p> <p>好，我们现在正式进入呃技术的部分。
在我这一讲里面所准备的很多的画面呢，<strong>由于太复杂了，所以常常会把这个整个画面占满，所以这标题我就挪到右手边来了。</strong>
首先我要带你去看vc6它的malloc的这个行为模式，马上就会看到。VC10，VC10已经很接近我们现在的版本了啊。</p> <p>嗯这个都已经无所谓了，反正它是一个比较新的版本。好，现在我们来看vc六，，现在左手边这一张图，这个在后头也会一再的出现，</p> <ul><li>这个是你的C++程序进入之前跟之后的行为，这是一个非常一般人都不知道的事情。</li> <li>关于这个呢，我有另外一门课叫做C++底层奥秘剖析之类的的题目，到时候题目一出来，你一看就知道了，会很深入的去谈谈这里面的每一个动作。</li></ul> <p>在这些动作里头，我们C加加的进入点是这个，main你写的程序在这里，如果是在windows程序底下，那就是wmain啊，不过地位跟这个相当啊。<strong>好，这个在这个之前做了这么多事情这个之后做了这么多事情，到底是谁来调用你的你写的面</strong>呢？</p> <p>这一张图叫callStart，调用的次序。调用的栈stack。这个从下往上看，下面一个箭头，这个是操作系统它的内核的部分，它会调用这个函数，叫mainCRTstartup（）
<strong>这个就是在vc六底下的所谓CRT所提供的函数。就是C。R、T，也是就这等于是C的标准库所提供的一个函数。</strong> <strong>名称是这</strong>样，在G<strong>NUC底下也有，只是名称不太相同。</strong>
不相同。</p> <p>这个进去之后，他做了这么多事情，最后他才终于都准备好了。
谁准备好了呢？C、R、T准备好，把他自己准备好了。然后他调用你的面，终于进入你的程序的接管。
在<strong>这些动作里头，我现在要引导你去看这一个函数『『黄色部分』』，这个叫heap_alloc_base，他是这样子进去的。</strong>
但是现在我要引导你看这一个函数这里头有这么一段动作，说</p> <p>如果say你要求的大小小于，这是一个常量，它定义的常量小于它的话小于等于它的话，那么就做这个动作，</p> <p>不是的话就到下面来做这个动作。</p> <p>这个是windows底下windows操作系统本身给你的含义，叫HeapAllocator的，就从这里来拿内存。所以这里有个判断呢，那这个大小是多少呢？3F8，也就是一零一六，这个thressold时候就是一个门槛，呃英文字典这个就是门槛的意思。
<strong>所以如果你要求的大小比这个门槛小的话，他就从这里去拿内存，如果比他大，他说呃抱歉，那我不为你服务了，由这里来服务。</strong></p> <h3 id="『联想』"><a href="#『联想』" class="header-anchor">#</a> 『联想』</h3> <ul><li>所以从这个地方我们可以感觉他也是在为小区快服务。
我们前面在讲分配器的时候，第二讲谈到分配器也是在为小区快服务。</li></ul> <p>而这里所谓的小是多小呢？1016，这个数字很奇怪。
一零一六已经接近1024，
零二四才是，我们觉得是一个好像一个一个一个整数值这样子，</p> <p><strong>事实上的确是1024。这边有个变化呢，后头再来说它</strong>。
<strong>所以所以我们可以理解了，在vc六以下的一个『复杂的内存管理』是应付小区快的。</strong></p> <h2 id="『新概念：sbh』"><a href="#『新概念：sbh』" class="header-anchor">#</a> 『新概念：<code>SBH</code>』</h2> <ul><li><code>Small Block Heap</code>，</li></ul> <p>在这个位置上，这个函数叫<code>sbh_thresold</code>是他的命名就是S、M、L，gif的意思。
<strong>我们就是要去追踪这一个设计，什么叫做SBH，我们就是要去看它的设计</strong>，</p> <p>这里面的设计由于我们已经对第二讲的分配器。有概念了，所以再过来当然就又轻松很多，<strong>因为很多的内存管理的概念是相通的。</strong>
好，这个是VC6.0</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092758281.png" alt="image-20210722092758281"></p> <p>下一页，这是VC10比较新的版本了。
这一个callStart，我仍然沿用vc六的那个次序，<strong>但是我把中间现在新版本vc10不存在的都打一个叉，把它划掉</strong>。
其中刚刚在上一页让你看的这个函数现在仍然存在，这个函数里头的设计是这样，源代码在这里。
嗯这个函数是这样子。
对这个名字呢怎么不一样呢？为什么啊为什么左边能够能够调用到右边呢？因为上面有一个defair，有一个define，所以啊你仔细体会一下，由于这个default所以其实左边被调用到右边这个函数来，</p> <p>这个函数里头就不再做这个switch home<strong>门槛的检测</strong>，里头这些动作都不是我们关心的，我们只关心最后这个动作，它无论是什么样的大小，他都调用操作系统的。heap_alloc的来提供服务。<strong>也就是说到了比较新的版本里头呢，不再有所谓的SBH这个东西了，他不再特别为小块内存来做管理，他通通交给操作系统去做</strong>，</p> <p><strong>这样的话我待会儿要带你去看vc六的那个精巧的设计，那有什么意义呢？到了新版本已经不见了。</strong> <strong>有意义！！！</strong> <strong>那些动作其实都被包装到这里头去了，操作系统也在做类似的动作。</strong>
我能够空口说白话，我能够有证据吗？？？</p> <p>有，但就不含在这个课程里头。</p> <p><strong>有另外一门课程在谈win——windows系统的管理，那个时候已经深入到操作系统层面</strong>了，我就会挖出一些证据。
告诉你，</p> <p>而现在您所学的这些内存管理呢都被搬到操作系统去了，所以在接下来的这个投影片里面，我所谈的全部都是vc6。
但他仍然存在。搬到操作系统层面。
好，这是我们这两张投影片。</p> <h3 id="『看到第12分钟了』"><a href="#『看到第12分钟了』" class="header-anchor">#</a> 『看到第12分钟了』</h3> <p>在刚刚的这个host，stack一个一个的调用次序里头。
哎对，请注意这边，这是vc六。
是这样啊，到了危机时呢，这些不见了。
那这三个不见了，这三个原来的名字叫什么？
叫SD。
H开头，所以也可以让你感觉SD。
H到了新版。
根本就不见了。
好在这个地方，我看看是不是这里啊还不是。
所以我们往下看，回到这边，这个看过了，vc六的，这个是vc十的。
好，我们再往下看。
我们现在来探讨sd。
h，我们想了解梅洛克里头的精巧的设计，就是这个s、b、h。
这个刚刚在调用的时候，这里头的第一个最重要的动作，我在进入面之前的第一个动作就是吸引。
inside。
从名称来看也知道它跟内存有关，所以我现在带你去看看he is in national的动作。
他要做什么样的初始化呢？
这里头这个动作是也呃我要先把因为这些就调用到win三二，windows的提供的API的函数，所以我要先把windows对内存的管理的一些概念先跟大家提一下。
windows本身维护了海量的内存，你可以跟他要求说，我帮我创建一个新就是一块空间了，一块独特的空间，我要给它命名。
然后呢今后我做的某些动作都是从这一块来取，我还可以跟他要求要另一块又换了个名字，我的其他的另外一些动作都是从那一块来取，所以这是一个逻辑上的把它分类。
现在在这个动作里头，马上就跟操作系统说，你给我一个系统多大呢？
这些数字我已经查过了，然后打出来给你看，四。
零、九、六这么大得到的这一块，我要给他命一个名称叫做c。
rt系统，这是一个全局变量啊，你可以想象说就是有一个指针指向这一块，这一块做什么用的呢？
命名叫c、r、d、t，想必就是将来后头呢要给cr t用的。
see，you，on，time。
level。
刚刚你所看的这些都是c、r、t的动作，所以这里所要求的内存都将要从这一块来呢？
这块多大是零。
九六。
四。
零九六不大呀。
那没关系，当你继续要的时候，操作系统自然会把它增长，所以这个初值不是太有意义。
好，这个拿到之后，接下来做这个动作，这个动作在右手边，他所做的事情。
好，七。
八K。
从谁那边拿呢？
这个这个是谁？
这个是就是左边这个。
所以刚刚说刚刚在左手边说请你给我四。
零九六这样一块啊，我要应付C、R、P的需求，然后接下去到这个地方就说，好，那现在我就从这一块里面去拿拿多少？
十六个。
header，这么大黑的是什么？
等一下就会介绍。
现在要十六个黑的。
我我用图画出来这个西shibor kit拿到的这个结果。
这等于是这就是一根指针，这个指针就指向十六个黑的头。
准备好了，在这里这整个动作是什么？
叫做shape in internet。
所以它的初始化就是把十六个黑的准备好，这里有个十六。
至于这一些变量呢，目前都不必去提它。
所以回到前面来，无论是新版的。
或者是跟前面旧版的都会进入这个international，而里头做的事就是分配了十六个黑的，我们很快就会去看看header长什么样子。
这个就是黑的结构，刚才那张图我是这么画的，其中的一个我以图形来表现，是这样。
怎么能够画出这张图呢？
靠的是它的数据结构。
在这里，我们来看看这里头有有有什么这三个这三个都是P to B、B to B就是一个昂三阴地球。
所以就是三十二个点，三十二位。
那么三个三十二位，其实呢它是把它其中两部分组合起来，这个命名叫high，这个叫low，还跟肉组合起来，其实是六十四个G的。
在这里，我花生比较长了，但是不能全部画出来，因为实在太多了，所以这边是点点点。
这是六十四个病，另外还有一个三十二B，那就画在上头，这确实是三十二，如果你很细心的去去数的话是三十二。
这些做什么用，我们现在暂暂时不讨论。
好，所以上面的图就是这个下面这三个栏目，另外还有两根指针，这两根指针现在在这个图上我没有画出来，后头再出现这个图的时候。
就会画出来了。
所以其实如果你在你的讲义上面呢，把这两边是把这个地方画两根指针，会能够更形象的表达它的定义，这就是美。
我其实最终是要一步一步地引导你去看，我们要跳好几页，先去看一下最后的结果是什么。
我们现在跳跳跳跳跳票。
行。
最后你会看到整个S、D、H长这个样子。
哦这个就是刚刚在看的，黑的有十六个。
这边点点点啊，我只画了两个，一开始只用到一个其他的十五个备用。
所以哦有两根指针现在已经画出来了。
好，后面的动作就是要一步一步的引导你去看它怎么长出这个东西，而长出这个东西做什么用呢？
他要用这一个数据结构去管理一块内存。
我现在可以先告诉你，他要管理email，用这么复杂的结构去管email的内存，那管理是要做什么用？
就是为了将来给出去回收都能够很快也能够消除这个碎片，要做这一为了这个目的。
所以我们现在有个概念，他为了做这些管理，真正要给出去的是email，但是为了要做这个管理呢，它消耗了这么多，我们后面可以把这些这些算是。
呃开销，over，hand。
为了那email这边消耗了这么多，这些通通都可以算出来啊它的成本是多少。
我们再回到前面。
好我们刚刚讲到这里，所以我现在要一步一步地带领你从这个黑的开始看它的变化。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092820458.png" alt="image-20210722092820458"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092840180.png" alt="image-20210722092840180"></p> <h2 id="⏳33-vc6内存分配（1）"><a href="#⏳33-vc6内存分配（1）" class="header-anchor">#</a> ⏳33.VC6内存分配（1）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092909241.png" alt="image-20210722092909241"></p> <p>嗯嗯嗯现在我们已经了解了这个第一个动作，keep，inness，legislation。
只是分配十六个头，头里面那个黑的里面是色的，什么东西我还不知道，不过就消耗了这些内存。
这内存从哪里来的？
赶快复习一下。
就是从那个特殊的系我们跟windows要的那个特殊的hp，叫c、r、t、h那一块来的。
在这里，keep这个字眼你就想象就是一堆内存，这样就可以了。
接下来开始现在只是一个初始化，接下来开始分配内存啊在很多很多地方都可能分配内存，现在都还没有进入你的面还没有进入你的程序。
进入你的程序之后，你也要分配内存。
千头万绪，我觉得有一个很棒的方法来引导你去看，就是看他的第一块内存是怎么分配的。
并且由于第一块内存的这个命令的出现，这个是申请的出现，使得它会长出那个复杂的结构出来，我们所谓的S、B、H出来，所以这个第一块。
好，我们来看第一款，这是一个很好的引导，所以检讨检讨一下。
刚刚这个一已经看过了，它里头调用的这一个也看过了。
你回到上个月，你就这这两个已经都讲过了，然后退回来进入下一个动作，叫I、O、I、N、I，T。
我在这里头的源代码发现了这个动作。
诶我怎么能看到这些源代码？
这是很神秘的东西吗？
不是，至少在vc不是，你安装vc就会有一个word，有一个子目录，上面名字我也忘了，可能叫叫c、r、t、sars，或或或什么的之类的，任何人都可以看到这一些源代码。
好，进去之后我发现里头做一个动作，这样这里头调用这其实是跟io相关的初始化，不过它需要内存，所以就做了这个动作。
这就是我所发现的第一次内存分配。
这个当然属于你了，这还没有进入你的面，但是这整个是你的程序的一部分。
是c，rt附着到跟你的程序附着在一起，绑在一起。
所以你的程序如果你能够去观察的话，你观察的第一块一定是这一个所有的程序都一样。
这个动作是什么？
这一个函数我们比较陌生，其实它就是上面这样，在源代码里面有分成是debug模式呢还是非dear模式？
如果没有定义的话，那么这一个名字就换成这一个名字。
v。
log啊，我们很熟悉了。
如果是第八个mod啊，这一个名字就换成这一个。
接下来我要带。
你看的是spark mo的底下，所以这个调用就等于是调用这个了。
蓝色的这个这个是什么？
放在这里。
my local debug就是这里的my local debug。
所以我标观察的时候才能够观察到哦原来他调用了这个函数。
i love。
you。
bug。
这里做什么事情呢？
这里这一个和这一个有什么差别吗？
差别只在于它安插了另外额外的一些东西。
这个格式哈等下会再讨论。
总之在这个地方你可以感觉他要分配内存分配多大。
这个数字是三十二，这个数字是八，叫io音。
B，I、O，info，我把它抽出来放在这里。
这是一个L加一个cvt。
加一个cvt，那就是四加一加一是六。
六将会被调整到八，除非你有特别设定编译器的那个对齐，不然会被调到八。
所以三十二乘以八就是二、五、六。
所有的程序一进来一定做这个动作一定是第一块就是两百五十六个字节，这个二、五、六在十六进位就是一、零、零，记住这个数字后面我们的例子啊，就会我我画的图就会出现一、零、零这个数字出来。
好，这就是第一次他就发出需求了。
发出需求。
好，我们再往下看。
刚刚谈到i、o、i、n、i、t，要用这一个函数，这个函数里头会继续调用，那么调用到这一个这个里头没有。
我现在要讲的事情不是很无关紧要，所以我们继续往下看，他又调用了这个函数，在这个函数里头有一段代码是这样。
什么事情呢？
它传进去的电量我这边没有办法写得非常清楚啊。
其实这个地方传进去的电量是这一个值，也就是刚刚的两百五十六个字节。
刚刚是从这个地方发起的，i、o、i、n、i，t，说他要两百五十六个字节，于是跑到这个函数来，这个就是这里就是两百五十六。
在这个地方去加了什么东西呢？
sat，of，这一个汉，后头又加了这一个这个数字就是四。
我们仔细看一下分，no，manage，人，size，这叫无人区的大小。
什么是无人区？
蛮有意思的，等一下再说。
所以这个的定义就是四。
前面这个呢science，of，这个紫色的这一个紫色的这个就是这里仔细看名称，这个叫做black，he的啊lucky的。
这一块是在第八个模式底下，准备附加到你的你。
所申请的内存之上这一块的定义是这样。
里头有几笔数据呢？
一二三四六七八。
下面这是注解，把这八个画成图，就是右边这样，我们来看看这八个，前两个是指针指针。
那目前都还没设置，现在事实上现在还没分配呢，现在只是在调整它的大小。
申请的时候，I、O、I、N、I、T申请的时候说他要一。
零零H，现在正在调整大小，要调整什么？
其实这一块就是一。
零零H。
首先调整上面。
这里加了这个东西，八格一、二、三、四、五、六、七、八，后头还要再加上一个四。
这这个是四，也就是说在debug mode底下，你要的大小会被它调整为更大一些。
多大呢？
这么大。
这个没有按照比例画。
这八格里面这个叫debug header，这个叫block header，不过我们我们在其他地方会看到专门给的bug用，所以叫D park header。
好，前面是两根指针啊，注意啊，我刚才已经说了还没有分配啊，只是说分配好之后要放这些东西。
第三个也是指针指向file。
name。
各位，这个是给bug用的哦。
所以在调试的过程里面都会看到一块内存，就调试器就可以从这个地方知道原来这一块内存是从哪一个文件的哪一行发出来的需求那就靠第三格和第四个，第四个叫line，number。
所以以现在这边来看的话，这一个winter将会指向一个字符串，写的是I、O、I、N，I，T，点C。
为什么呢？
因为是从这里发出来的，它的位置就是在这个file里头第几行？
第八十一行。
至于这些数字。
是怎么塞进去的？
现在还没看到，我们只看到这空间准备放这个东西。
好，这个是第四个。
再来呢五、六、七、八也是什么？
第五个说是data size。
data size将会记录真正的大小，一，零、零二，七。
第六格呢。
fuck。
you。
yes。
这个等下再解释。
第七个，这是一个流水号嘛，现在是第一块，所以它这个编号是一。
第八个呢？
第八个是一个以字符形成的。
喂这耳瑞多大？
这个数字就是上面那个字。
也就是四个字符，这四个字符在后面的代码里面将会被填入这个字。
然后这个下去之后就是真正要的大小了之后还有四个字符就是在这里打算分配的。
那这四个字符呢也会被填这个纸这两个值这个颜色的这两个值当成一个一个栏杆，或者当成一个篱笆啊这一块保护住。
因为现在是在调试模式下，所以调试器有办法帮我们检查，万一这一块被使用者这样写写写写一直写呢？
包括了边境，把这个破坏掉了啊，调试器就可以检查出来。
这就是因为现在的看现在的设计里头，准备在这个上下夹一个什么呢？
加一个无人区，N、M、L无人区，这是为了调试器而设计的。
好，所以我们整理一下，刚刚啊在这个地方发出了第一次的内存分配的需求，于是一直调用进去。
再用到这一个函数的时候，把这个空间扩大了，但是还没有分配啊扩大完毕之后，这个动作要用蓝色的这个，于是这边就进入了下一个函数。
olive，care，base，这里shift，ok的。
base。
这一次要分配的就是这个已经调整过的大小，叫black。
set。
自己当初在看这一些调用动作的时候，也是被这些函数名称弄得头昏脑胀。
现在大家看很多次很多次啊这个，花很多时间慢慢能够感觉到它对这些函数命名的意义。
我可以把这个心得告诉你，这里面谈到的black就是真正要割出去的那一块啊，不是你申请的大小，是已经附加了东西之后的大小。
这一个叫black，所以这边说要二楼呃lucy的一个block。
那么这边呢？
A，L、K一个debug其实就是在调整，要加上debug。
header。
啊我们现在谈到谈到这个地方嘛，对吧？
在这地方你看到了，它只是在调整大小，它调整什么呢？
它增加了第八个黑的下面这个你要把它叫黑的也怪怪的。
黑的应该带头嘛，这个是在尾，不过这个是只是一个称呼上的习惯。
反正这些就是绿色以外的这些就是给给bug用。
好，我们继续往下，就这一个函数，现在看到了啊，接下去调用的呢这个叫A、L、K、bs，我们再往下看。
好，进入二K、B、S之前，我还准备了这一章。
这个地方啊，所以现在还没进入case啊，我刚刚讲早了一点，还没有进入，现在还在。
这个函数刚刚上一页这函数这边有接续下夜到了下一页呢，这边有承接上一页，这是同一个函数在这里所做的事情，在调整指针，所以我们这边认识了有一根指针叫first block，还有一根指针叫last plan。
也就是说这些plus有一个头，他那个尾指着他尾巴，到现在我没有画出来，因为这个其实有好几个，现在我们在谈的是第一个，后面的运作变化就会有好几个。
所以这个地方在调整头尾。
在这边我要带给你一个印象哈，从这一段代码。
对我画的图就让你感觉让你知道你所分配的所有的内存块经过milk所分配的，通通都被他登记起来，用链表串起来。
即使这一块已经给你了，即使已经给你了，也在他的掌控之中。
所谓他，你可以说就是这个S、B、H。
不过这是在调试模式下。
呃现在你也许你可以恍然大悟了，为什么调试器这么厉害，它可以做一些它可以追踪我要的内存等等等这么厉害的动作，其实是因为在调试模式底下多了这些东西。
多了什么多了。
深灰色之外的这些东西。
好，所以这边请大家注意，就是由指针两根指针指向头尾。
我在上一讲里面谈到最后的时候，谈到，我们能不能能够去去追踪这个milk的行为呢？
我当时说如果你够厉害的话，你的层次够高就可以。
其中一个够高的方式就是你知道这两根指针这个是一个全局的，它是C、R、T提供，但是C、R、T也属于你的一部分呢，那最后是成为你的一个整个一个可执行文件。
所以你当然也可以像调试器一样，你现在就把自己扮演成调试器。
你就你已经知道这个名字了，你就可以把这个走一遍。
不过当然必须在调试模式下才会有这根指针吗？
你把这个走一遍，在每一块里头你都能够看到大小，这个大小是真正的大小。
我们把这个图太小了，我拿到上一页这一块就是上一页的这种东西啊，我追踪到这一块之后，就可以看到里头这个大小一。
零。
零，就是真正人家要的大小。
可是这整块block是多大呢？
这其实不是看这里，我们也可以加自己加起来，但是这个其实更往上看，有一个东西叫copy。
看那里。
就知道了。
好，回到这里。
啊所以现在进行的是这个这个函数认识了两根很重要的指针。
以前以后。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722092935650.png" alt="image-20210722092935650"></p> <h2 id="⏳34-vc6内存分配（2）"><a href="#⏳34-vc6内存分配（2）" class="header-anchor">#</a> ⏳34.VC6内存分配（2）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093021365.png" alt="image-20210722093021365"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093048224.png" alt="image-20210722093048224"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093109394.png" alt="image-20210722093109394"></p> <h2 id="⏳35-vc6内存分配（3）"><a href="#⏳35-vc6内存分配（3）" class="header-anchor">#</a> ⏳35.VC6内存分配（3）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093143541.png" alt="image-20210722093143541"></p> <h2 id="⏳36-vc6内存分配（4）"><a href="#⏳36-vc6内存分配（4）" class="header-anchor">#</a> ⏳36.VC6内存分配（4）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093217713.png" alt="image-20210722093217713"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093255158.png" alt="image-20210722093255158"></p> <h2 id="⏳37-vc6内存分配（5）"><a href="#⏳37-vc6内存分配（5）" class="header-anchor">#</a> ⏳37.VC6内存分配（5）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093350252.png" alt="image-20210722093350252"></p> <h2 id="⏳38-sbh行为分析-分配-释放之连续动作图解（1）"><a href="#⏳38-sbh行为分析-分配-释放之连续动作图解（1）" class="header-anchor">#</a> ⏳38.SBH行为分析-分配+释放之连续动作图解（1）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093415201.png" alt="image-20210722093415201"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093441466.png" alt="image-20210722093441466"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093516110.png" alt="image-20210722093516110"></p> <h2 id="⏳39-sbh行为分析-分配-释放之连续动作图解（2）"><a href="#⏳39-sbh行为分析-分配-释放之连续动作图解（2）" class="header-anchor">#</a> ⏳39.SBH行为分析-分配+释放之连续动作图解（2）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093603111.png" alt="image-20210722093603111"></p> <h2 id="⏳40-sbh行为分析-分配-释放之连续动作图解（3）"><a href="#⏳40-sbh行为分析-分配-释放之连续动作图解（3）" class="header-anchor">#</a> ⏳40.SBH行为分析-分配+释放之连续动作图解（3）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093645192.png" alt="image-20210722093645192"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093716939.png" alt="image-20210722093716939"></p> <h2 id="⏳41-sbh行为分析-分配-释放之连续动作图解（4）"><a href="#⏳41-sbh行为分析-分配-释放之连续动作图解（4）" class="header-anchor">#</a> ⏳41.SBH行为分析-分配+释放之连续动作图解（4）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093756127.png" alt="image-20210722093756127"></p> <h2 id="⏳42-vc6内存管理free-p-（上）"><a href="#⏳42-vc6内存管理free-p-（上）" class="header-anchor">#</a> ⏳42.VC6内存管理free(p)（上）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722093828399.png" alt="image-20210722093828399"></p> <h2 id="⏳43-vc6内存管理总结（上）"><a href="#⏳43-vc6内存管理总结（上）" class="header-anchor">#</a> ⏳43.VC6内存管理总结（上）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722094025324.png" alt="image-20210722094025324"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722094045640.png" alt="image-20210722094045640"></p> <h2 id="⏳44-vc6内存管理总结（下）"><a href="#⏳44-vc6内存管理总结（下）" class="header-anchor">#</a> ⏳44.VC6内存管理总结（下）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722094133544.png" alt="image-20210722094133544"></p> <p>前面我曾经。
对你提出一个问题。
当你归还释放掉所有的内存块，你是客户你是客户啊，你所有的mlk 都还给他了。那么s b a h 系统会呈现什么面貌呢？
我刚才已经告诉过你，他会回复到一个初始状态。
就是这种。
一个group 呃，这个叫初始状态，其实干安全提过了。
所以这张图给大家。
形象上的看一看。
这八块是不会合并的。
好。
整个my lock 所有的细节我们。
我不敢说所有的细节，因为整个是太繁复了，百分之九十百分之九十五。
所以重要的部分都谈过了没？lk 的整个技术到此。
结束。
知道了这些细节以后，首先我会去想那。
这诊断在debug 模式底下，所有的区块其实都是被一根指针链子。我们前面介绍过所有的区块。
即使sdh 啊他掌握的他给了我，他他仍然有指针链子，他这样调试器才能够追踪。
那我应用端。
我不小心知道了这个秘密。
我可不可以也像你bug 那样去。
追踪一遍呢。
当然可以，我已经试过了。傍晚。
vc.
不敢说是所有的版本啊，但是在vc 六就已经提供了这种函数。
这是他把它叫做什么，叫做西state reporting function。
就是在登记系统的状态的一些一些一些登记用的整理数据给你看的一些函数。
vc 六有提供你手上的新版本。再去查一查有没有这些函数。
这些函数也都是有源代码的，他他就是c e r t 的一部分。我前面提过了vc。
的标准库里头，整个cid 的源代码是给你的。
我已经看过他的源代码，这里头其实就是去追踪我刚刚所说的那一个链表。
在调试模式底下。
调试模式底下才有点八个header 才能够去追踪它。
然后可以去看看目前呃有多少块。
哪些块是crt 给的，呃，施压t 所是申请的，哪些块是我应用程序所申请的？
啊，他们的量是多少？
都可以调用这些函数。看得出来。我不带你去看这些函数啊，你手上也一定会有完整的文件文档，你可以去试试看。
你甚至于可以去看看他的源代码。
像对于你提升你对于刚刚所说我所说的vc the mallock 的这个技术啊，对于这个提升是有帮助的。
好，有这么一组这个特殊的函数。
技术面已经全部探讨完毕了。
对。
作为一个。
正大局观的一个总整理。
我们在第二讲谈呢是跟慕斯的分配器。
到了第三讲谈的是vc the milk。
这是两个不同的系统。
啊，这是投这个我可以拿来一起想嘛，我要乱点鸳鸯谱嘛。
前面我提过触类旁通这个字眼，其实mellot k 的动作，这些行为呢我们看的是vc 的版本。
在格洛斯。
也有一样的动作，而且还更复杂一些。我们已经没有必要去看各个版本。
在不同平台下的各个版本的做法没有必要了。我们知道啊原来。
may lock 的做法。
这一开始不就介绍了一个人叫巴格利吗？他已经发展出自整个算法，并且广被采纳。
所以你如果在耿慕斯底下，他的vv ok 也是差不多，就这种行为也是每一块带着八个字节的枯井。
等等等等等。
所以我现在把这两件事情哈分配器，按第二讲的分配器和第三讲的mlk 把它合在一起。
希望你能够更让你的整个心里头的整张图更清楚。
分配器最终要内存意见还是跟ml 一药。
分配器这边有十六条链表。
他管的是最高到一百二十八个字节。
他每次要的时候都会落到由于这个其实都很小啊，一百二十八。
所以他mlk 药的时候。
都小于呃，他跟梅勒菲娅维洛克自己的定义是小区块叫一k。
所以他跟他要永远是小于k。
呃。
或者说永远啊等一下这个在想，如果都小于。
一k 的话就有没有可能。
为了会快不快。
速度快不快，非常快，它里头有这么复杂的管理。
所以。
右上角这个分配器，它之所以做这些管理，不是为了要提升速度。
为了和已经够快了。
你调用他一百万是跟加上他五十万次呢，恐怕这个相差无几。
目的不是为了提升速度，速度已经够令人放心了。
目睹目的是为了去除估计。
你看这个图，这一些东西的上头，这个是固体。
他一次性的分配只浪费了这个酷，可是他可以切成这么多小块。
这如果你把这两者合在一起想。
你你可以发挥很多，你从很多的细节去看他们两者的关联性。
好。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722094207090.png" alt="image-20210722094207090"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722094227747.png" alt="image-20210722094227747"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722094246414.png" alt="image-20210722094246414"></p> <p>我们再往下。这一张图在整个课程的一开始就提过。
我们在C++程序可以通过这个这个这个的方式去要到内存，最终都跑到梅勒克莱。
而我们现在已经学习到了。
library 这个样子。他其实有缺点。他的缺点就是他不愿意还，他比较霸道。
好，这个到第四讲，我们再来来处理他o k 分配器长这样。
we lock 长这样。
都有非常复杂的设计。
事实上我可以告诉你。
没那个往下调用os 也有类似的设计，也是一些自由区呃，自由链表。
就是用内存池的方式做管理。
叠床架屋。
叠床架屋。
第一阶到高阶。
这是不是一种浪费？
是。
是一种浪费。
有没有必要？
有。
有必要，为什么呢？
这个是c。
的层次它是跨平台的，他并没有说他要依附在哪一个作业系统上面，操作系统上面。
所以他不能够去预设。
他不能预设他下面的操作系统有没有做管理。
同样的道理。
上面这个分配器。
他最终会调用没有lok 他也不能够去预测这个mello 有没有做这种管理。
因为他是c 佳佳标准户。
他不能够依赖底层了吃的东西，所以每一个层次呢都不敢去依赖。下面有不甘，有先决的一个。
预想，所以自己都哪一套。
的确是浪费，有没有必要呢？
有必要。
那也没办法。
我在这个第三讲，现在第三讲的一开始我要提过vc 六是这样，vc 10是这样，你会看到了危机时。
vc 时就没有没到里头就没有这个了。
他直接调用glk，他把任务都他把责任都交给他了。
那我们只能说。
vc visual c 加加他就专门是为windows 而写的，所以他已经自己公司把自己独家发展的。他知道下面。
windows 呢有这个设计，他就舍弃了他的这一部分。
我们把这些东西放在一起看。
现在你可不可以检讨一下你自己，你对mlk 的理解是不是有一个大的推翻，以前是不是有很多误解，认为他很慢，认为他做了什么等等等等等等。</p> <p>有了这些设计之后，你还需要自己写一个分配器吗？
也许对很多很多人的。答案是否定的。这是我们在学这一些既有的系统的另外一个大收获。
如果你真的真的有需要写的话，好啊，这些都是这些技巧都可以借鉴。但是很可能呢其实已经不需要写了。
这就是我们的第三家，整个在这边，最后一张投影片结束。</p> <h2 id="✅第4讲-loki-allocator"><a href="#✅第4讲-loki-allocator" class="header-anchor">#</a> ✅第4讲-<code>loki::allocator</code></h2> <h2 id="_45-上中下三个classes分析"><a href="#_45-上中下三个classes分析" class="header-anchor">#</a> 45.上中下三个classes分析</h2> <ul><li>成竹在胸</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722094336265.png" alt="image-20210722094336265"></p> <h2 id="_46-loki-allocator行为图解"><a href="#_46-loki-allocator行为图解" class="header-anchor">#</a> 46.Loki_allocator行为图解</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095229638.png" alt="image-20210722095229638"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095247177.png" alt="image-20210722095247177"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095314738.png" alt="image-20210722095314738"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095332828.png" alt="image-20210722095332828"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095356993.png" alt="image-20210722095356993"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095511758.png" alt="image-20210722095511758"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095531112.png" alt="image-20210722095531112"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095617141.png" alt="image-20210722095617141"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095638661.png" alt="image-20210722095638661"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095655192.png" alt="image-20210722095655192"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095716495.png" alt="image-20210722095716495"></p> <h2 id="_47-class-fixedallocator分析（上）"><a href="#_47-class-fixedallocator分析（上）" class="header-anchor">#</a> 47.class FixedAllocator分析（上）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095748612.png" alt="image-20210722095748612"></p> <h2 id="_48-class-fixedallocator分析（下）"><a href="#_48-class-fixedallocator分析（下）" class="header-anchor">#</a> 48.class FixedAllocator分析（下）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095812956.png" alt="image-20210722095812956"></p> <ul><li>侯捷</li> <li>侯捷</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095828858.png" alt="image-20210722095828858"></p> <h2 id="_49-loki-allocator总结"><a href="#_49-loki-allocator总结" class="header-anchor">#</a> 49.Loki_allocator总结</h2> <ul><li>Loki allocator检讨</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722095852577.png" alt="image-20210722095852577"></p> <h2 id="✅第5讲、其他"><a href="#✅第5讲、其他" class="header-anchor">#</a> ✅第5讲、其他</h2> <h2 id="_50-gnu-c-对allocators的描述"><a href="#_50-gnu-c-对allocators的描述" class="header-anchor">#</a> 50.GNU C++对allocators的描述</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210717095143217.png" alt="image-20210717095143217"></p> <ul><li>下面开始描述</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210717095246464.png" alt="image-20210717095246464"></p> <ul><li>描述</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210717095435535.png" alt="image-20210717095435535"></p> <h3 id="智能型"><a href="#智能型" class="header-anchor">#</a> 智能型</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210717103106673.png" alt="image-20210717103106673"></p> <ul><li>demommm</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210717103521657.png" alt="image-20210717103521657"></p> <ul><li>demommm</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210717103634068.png" alt="image-20210717103634068"></p> <h2 id="_51-vs2013标准分配器-g4-9标准分配器与new-allocator以及g4-9malloc"><a href="#_51-vs2013标准分配器-g4-9标准分配器与new-allocator以及g4-9malloc" class="header-anchor">#</a> 51.<code>VS2013</code>标准分配器&amp;<code>G4.9</code>标准分配器与new_allocator以及G4.9malloc</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>51.VS2013标准分配器
&amp;G4.9标准分配器
与new_allocator
以及G4.9malloc
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210717103930992.png" alt="image-20210717103930992"></p> <ul><li>demommm开始11</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195105559.png" alt="image-20210719195105559"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>反
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195149968.png" alt="image-20210719195149968"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>翻译
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h2 id="_52-g4-9array-allocator"><a href="#_52-g4-9array-allocator" class="header-anchor">#</a> 52.G4.9<code>array_allocator</code></h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195230637.png" alt="image-20210719195230637"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>...
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195311605.png" alt="image-20210719195311605"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195427026.png" alt="image-20210719195427026"></p> <h2 id="_53-g4-9-debug-allocator"><a href="#_53-g4-9-debug-allocator" class="header-anchor">#</a> 53.G4.9 debug_allocator</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195609915.png" alt="image-20210719195609915"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="C:/Users/MaxWell/AppData/Roaming/Typora/typora-user-images/image-20210719195635363.png" alt="image-20210719195635363"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>////
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195714498.png" alt="image-20210719195714498"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195743264.png" alt="image-20210719195743264"></p> <h2 id="_54-bitmap-allocator-上"><a href="#_54-bitmap-allocator-上" class="header-anchor">#</a> 54.bitmap_allocator(上)</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195820843.png" alt="image-20210719195820843"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195856900.png" alt="image-20210719195856900"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719195924602.png" alt="image-20210719195924602"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200008267.png" alt="image-20210719200008267"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200039264.png" alt="image-20210719200039264"></p> <h2 id="_55-bitmap-allocator（下）"><a href="#_55-bitmap-allocator（下）" class="header-anchor">#</a> 55.bitmap_allocator（下）</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200111467.png" alt="image-20210719200111467"></p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200142606.png" alt="image-20210719200142606"></p> <ul><li>测试</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200212476.png" alt="image-20210719200212476"></p> <ul><li>测试</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200258803.png" alt="image-20210719200258803"></p> <ul><li>测试</li></ul> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200344301.png" alt="image-20210719200344301"></p> <ul><li>测试</li></ul> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200412847.png" alt="image-20210719200412847"></p> <ul><li>测试</li></ul> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200446593.png" alt="image-20210719200446593"></p> <ul><li>测试</li></ul> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210719200618745.png" alt="image-20210719200618745"></p> <h2 id="参考资料"><a href="#参考资料" class="header-anchor">#</a> 参考资料</h2> <ul><li>C++<a href="https://mooc.study.163.com/smartSpec/detail/1001137001.htm" target="_blank" rel="noopener noreferrer">网易云微专业<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，侯捷</li></ul></div> <div class="page-edit"><!----> <!----></div> <!----> </div> <!----></div></div>
    <script src="/assets/js/app.c70e21ad.js" defer></script><script src="/assets/js/31.831b195d.js" defer></script>
  </body>
</html>
